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

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). 

5 

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 

13 

14from django.core.exceptions import ImproperlyConfigured 

15from django.utils.functional import SimpleLazyObject, cached_property 

16from django.utils.version import get_version_tuple 

17 

18logger = logging.getLogger("django.contrib.gis") 

19 

20 

21def load_geos(): 

22 # Custom library path set? 

23 try: 

24 from django.conf import settings 

25 

26 lib_path = settings.GEOS_LIBRARY_PATH 

27 except (AttributeError, ImportError, ImproperlyConfigured, OSError): 

28 lib_path = None 

29 

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) 

41 

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 

50 

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 

71 

72 

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) 

77 

78 

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) 

86 

87 

88notice_h = NOTICEFUNC(notice_h) 

89 

90ERRORFUNC = CFUNCTYPE(None, c_char_p, c_char_p) 

91 

92 

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) 

100 

101 

102error_h = ERRORFUNC(error_h) 

103 

104# #### GEOS Geometry C data structures, and utility functions. #### 

105 

106 

107# Opaque GEOS geometry structures, used for GEOM_PTR and CS_PTR 

108class GEOSGeom_t(Structure): 

109 pass 

110 

111 

112class GEOSPrepGeom_t(Structure): 

113 pass 

114 

115 

116class GEOSCoordSeq_t(Structure): 

117 pass 

118 

119 

120class GEOSContextHandle_t(Structure): 

121 pass 

122 

123 

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) 

129 

130 

131lgeos = SimpleLazyObject(load_geos) 

132 

133 

134class GEOSFuncFactory: 

135 """ 

136 Lazy loading of GEOS functions. 

137 """ 

138 

139 argtypes = None 

140 restype = None 

141 errcheck = None 

142 

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 

151 

152 def __call__(self, *args): 

153 return self.func(*args) 

154 

155 @cached_property 

156 def func(self): 

157 from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc 

158 

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 

165 

166 

167def geos_version(): 

168 """Return the string version of the GEOS library.""" 

169 return lgeos.GEOSversion() 

170 

171 

172def geos_version_tuple(): 

173 """Return the GEOS version as a tuple (major, minor, subminor).""" 

174 return get_version_tuple(geos_version().decode())