Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/django/contrib/gis/geos/libgeos.py: 0%
91 statements
« prev ^ index » next coverage.py v7.0.5, created at 2023-01-17 06:13 +0000
« prev ^ index » next coverage.py v7.0.5, created at 2023-01-17 06:13 +0000
1"""
2 This module houses the ctypes initialization procedures, as well
3 as the notice and error handler function callbacks (get called
4 when an error occurs in GEOS).
6 This module also houses GEOS Pointer utilities, including
7 get_pointer_arr(), and GEOM_PTR.
8"""
9import logging
10import os
11from ctypes import CDLL, CFUNCTYPE, POINTER, Structure, c_char_p
12from ctypes.util import find_library
14from django.core.exceptions import ImproperlyConfigured
15from django.utils.functional import SimpleLazyObject, cached_property
16from django.utils.version import get_version_tuple
18logger = logging.getLogger("django.contrib.gis")
21def load_geos():
22 # Custom library path set?
23 try:
24 from django.conf import settings
26 lib_path = settings.GEOS_LIBRARY_PATH
27 except (AttributeError, ImportError, ImproperlyConfigured, OSError):
28 lib_path = None
30 # Setting the appropriate names for the GEOS-C library.
31 if lib_path:
32 lib_names = None
33 elif os.name == "nt":
34 # Windows NT libraries
35 lib_names = ["geos_c", "libgeos_c-1"]
36 elif os.name == "posix":
37 # *NIX libraries
38 lib_names = ["geos_c", "GEOS"]
39 else:
40 raise ImportError('Unsupported OS "%s"' % os.name)
42 # Using the ctypes `find_library` utility to find the path to the GEOS
43 # shared library. This is better than manually specifying each library name
44 # and extension (e.g., libgeos_c.[so|so.1|dylib].).
45 if lib_names:
46 for lib_name in lib_names:
47 lib_path = find_library(lib_name)
48 if lib_path is not None:
49 break
51 # No GEOS library could be found.
52 if lib_path is None:
53 raise ImportError(
54 'Could not find the GEOS library (tried "%s"). '
55 "Try setting GEOS_LIBRARY_PATH in your settings." % '", "'.join(lib_names)
56 )
57 # Getting the GEOS C library. The C interface (CDLL) is used for
58 # both *NIX and Windows.
59 # See the GEOS C API source code for more details on the library function calls:
60 # https://libgeos.org/doxygen/geos__c_8h_source.html
61 _lgeos = CDLL(lib_path)
62 # Here we set up the prototypes for the initGEOS_r and finishGEOS_r
63 # routines. These functions aren't actually called until they are
64 # attached to a GEOS context handle -- this actually occurs in
65 # geos/prototypes/threadsafe.py.
66 _lgeos.initGEOS_r.restype = CONTEXT_PTR
67 _lgeos.finishGEOS_r.argtypes = [CONTEXT_PTR]
68 # Set restype for compatibility across 32 and 64-bit platforms.
69 _lgeos.GEOSversion.restype = c_char_p
70 return _lgeos
73# The notice and error handler C function callback definitions.
74# Supposed to mimic the GEOS message handler (C below):
75# typedef void (*GEOSMessageHandler)(const char *fmt, ...);
76NOTICEFUNC = CFUNCTYPE(None, c_char_p, c_char_p)
79def notice_h(fmt, lst):
80 fmt, lst = fmt.decode(), lst.decode()
81 try:
82 warn_msg = fmt % lst
83 except TypeError:
84 warn_msg = fmt
85 logger.warning("GEOS_NOTICE: %s\n", warn_msg)
88notice_h = NOTICEFUNC(notice_h)
90ERRORFUNC = CFUNCTYPE(None, c_char_p, c_char_p)
93def error_h(fmt, lst):
94 fmt, lst = fmt.decode(), lst.decode()
95 try:
96 err_msg = fmt % lst
97 except TypeError:
98 err_msg = fmt
99 logger.error("GEOS_ERROR: %s\n", err_msg)
102error_h = ERRORFUNC(error_h)
104# #### GEOS Geometry C data structures, and utility functions. ####
107# Opaque GEOS geometry structures, used for GEOM_PTR and CS_PTR
108class GEOSGeom_t(Structure):
109 pass
112class GEOSPrepGeom_t(Structure):
113 pass
116class GEOSCoordSeq_t(Structure):
117 pass
120class GEOSContextHandle_t(Structure):
121 pass
124# Pointers to opaque GEOS geometry structures.
125GEOM_PTR = POINTER(GEOSGeom_t)
126PREPGEOM_PTR = POINTER(GEOSPrepGeom_t)
127CS_PTR = POINTER(GEOSCoordSeq_t)
128CONTEXT_PTR = POINTER(GEOSContextHandle_t)
131lgeos = SimpleLazyObject(load_geos)
134class GEOSFuncFactory:
135 """
136 Lazy loading of GEOS functions.
137 """
139 argtypes = None
140 restype = None
141 errcheck = None
143 def __init__(self, func_name, *, restype=None, errcheck=None, argtypes=None):
144 self.func_name = func_name
145 if restype is not None:
146 self.restype = restype
147 if errcheck is not None:
148 self.errcheck = errcheck
149 if argtypes is not None:
150 self.argtypes = argtypes
152 def __call__(self, *args):
153 return self.func(*args)
155 @cached_property
156 def func(self):
157 from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc
159 func = GEOSFunc(self.func_name)
160 func.argtypes = self.argtypes or []
161 func.restype = self.restype
162 if self.errcheck:
163 func.errcheck = self.errcheck
164 return func
167def geos_version():
168 """Return the string version of the GEOS library."""
169 return lgeos.GEOSversion()
172def geos_version_tuple():
173 """Return the GEOS version as a tuple (major, minor, subminor)."""
174 return get_version_tuple(geos_version().decode())