14
14
15
15
from django .contrib .gis .geos .error import GEOSException
16
16
from django .core .exceptions import ImproperlyConfigured
17
+ from django .utils .functional import SimpleLazyObject
17
18
18
19
logger = logging .getLogger ('django.contrib.gis' )
19
20
20
- # Custom library path set?
21
- try :
22
- from django .conf import settings
23
- lib_path = settings .GEOS_LIBRARY_PATH
24
- except (AttributeError , EnvironmentError ,
25
- ImportError , ImproperlyConfigured ):
26
- lib_path = None
27
-
28
- # Setting the appropriate names for the GEOS-C library.
29
- if lib_path :
30
- lib_names = None
31
- elif os .name == 'nt' :
32
- # Windows NT libraries
33
- lib_names = ['geos_c' , 'libgeos_c-1' ]
34
- elif os .name == 'posix' :
35
- # *NIX libraries
36
- lib_names = ['geos_c' , 'GEOS' ]
37
- else :
38
- raise ImportError ('Unsupported OS "%s"' % os .name )
39
-
40
- # Using the ctypes `find_library` utility to find the path to the GEOS
41
- # shared library. This is better than manually specifying each library name
42
- # and extension (e.g., libgeos_c.[so|so.1|dylib].).
43
- if lib_names :
44
- for lib_name in lib_names :
45
- lib_path = find_library (lib_name )
46
- if lib_path is not None :
47
- break
48
-
49
- # No GEOS library could be found.
50
- if lib_path is None :
51
- raise ImportError (
52
- 'Could not find the GEOS library (tried "%s"). '
53
- 'Try setting GEOS_LIBRARY_PATH in your settings.' %
54
- '", "' .join (lib_names )
55
- )
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
- # http://geos.refractions.net/ro/doxygen_docs/html/geos__c_8h-source.html
61
- lgeos = CDLL (lib_path )
21
+
22
+ def load_geos ():
23
+ # Custom library path set?
24
+ try :
25
+ from django .conf import settings
26
+ lib_path = settings .GEOS_LIBRARY_PATH
27
+ except (AttributeError , EnvironmentError ,
28
+ ImportError , ImproperlyConfigured ):
29
+ lib_path = None
30
+
31
+ # Setting the appropriate names for the GEOS-C library.
32
+ if lib_path :
33
+ lib_names = None
34
+ elif os .name == 'nt' :
35
+ # Windows NT libraries
36
+ lib_names = ['geos_c' , 'libgeos_c-1' ]
37
+ elif os .name == 'posix' :
38
+ # *NIX libraries
39
+ lib_names = ['geos_c' , 'GEOS' ]
40
+ else :
41
+ raise ImportError ('Unsupported OS "%s"' % os .name )
42
+
43
+ # Using the ctypes `find_library` utility to find the path to the GEOS
44
+ # shared library. This is better than manually specifying each library name
45
+ # and extension (e.g., libgeos_c.[so|so.1|dylib].).
46
+ if lib_names :
47
+ for lib_name in lib_names :
48
+ lib_path = find_library (lib_name )
49
+ if lib_path is not None :
50
+ break
51
+
52
+ # No GEOS library could be found.
53
+ if lib_path is None :
54
+ raise ImportError (
55
+ 'Could not find the GEOS library (tried "%s"). '
56
+ 'Try setting GEOS_LIBRARY_PATH in your settings.' %
57
+ '", "' .join (lib_names )
58
+ )
59
+ # Getting the GEOS C library. The C interface (CDLL) is used for
60
+ # both *NIX and Windows.
61
+ # See the GEOS C API source code for more details on the library function calls:
62
+ # http://geos.refractions.net/ro/doxygen_docs/html/geos__c_8h-source.html
63
+ _lgeos = CDLL (lib_path )
64
+ # Here we set up the prototypes for the initGEOS_r and finishGEOS_r
65
+ # routines. These functions aren't actually called until they are
66
+ # attached to a GEOS context handle -- this actually occurs in
67
+ # geos/prototypes/threadsafe.py.
68
+ _lgeos .initGEOS_r .restype = CONTEXT_PTR
69
+ _lgeos .finishGEOS_r .argtypes = [CONTEXT_PTR ]
70
+ return _lgeos
71
+
62
72
<
10000
td data-grid-cell-id="diff-8b3d9bdd211601af93cf0acd8c8b23cca2451a981eb88d830859dc5ac2399c5b-62-72-2" data-line-anchor="diff-8b3d9bdd211601af93cf0acd8c8b23cca2451a981eb88d830859dc5ac2399c5bR72" data-selected="false" role="gridcell" style="background-color:var(--bgColor-default);padding-right:24px" tabindex="-1" valign="top" class="focusable-grid-cell diff-text-cell right-side-diff-cell left-side">
63
73
# The notice and error handler C function callback definitions.
64
74
# Supposed to mimic the GEOS message handler (C below):
@@ -120,11 +130,42 @@ def get_pointer_arr(n):
120
130
GeomArr = GEOM_PTR * n
121
131
return GeomArr ()
122
132
133
+
134
+ lgeos = SimpleLazyObject (load_geos )
135
+
136
+
137
+ class GEOSFuncFactory (object ):
138
+ argtypes = None
139
+ restype = None
140
+ errcheck = None
141
+
142
+ def __init__ (self , func_name , * args , ** kwargs ):
143
+ self .func_name = func_name
144
+ self .restype = kwargs .pop ('restype' , self .restype )
145
+ self .errcheck = kwargs .pop ('errcheck' , self .errcheck )
146
+ self .argtypes = kwargs .pop ('argtypes' , self .argtypes )
147
+ self .args = args
148
+ self .kwargs = kwargs
149
+ self .func = None
150
+
151
+ def __call__ (self , * args , ** kwargs ):
152
+ if self .func is None :
153
+ self .func = self .get_func (* self .args , ** self .kwargs )
154
+ return self .func (* args , ** kwargs )
155
+
156
+ def get_func (self , * args , ** kwargs ):
157
+ from django .contrib .gis .geos .prototypes .threadsafe import GEOSFunc
158
+ func = GEOSFunc (self .func_name )
159
+ func .argtypes = self .argtypes or []
160
+ func .restype = self .restype
161
+ if self .errcheck :
162
+ func .errcheck = self .errcheck
163
+ return func
164
+
165
+
123
166
# Returns the string version of the GEOS library. Have to set the restype
124
167
# explicitly to c_char_p to ensure compatibility across 32 and 64-bit platforms.
125
- geos_version = lgeos .GEOSversion
126
- g
E41F
eos_version .argtypes = None
127
- geos_version .restype = c_char_p
168
+ geos_version = GEOSFuncFactory ('GEOSversion' , restype = c_char_p )
128
169
129
170
# Regular expression should be able to parse version strings such as
130
171
# '3.0.0rc4-CAPI-1.3.3', '3.0.0-CAPI-1.4.1', '3.4.0dev-CAPI-1.8.0' or '3.4.0dev-CAPI-1.8.0 r0'
@@ -147,18 +188,3 @@ def geos_version_info():
147
188
raise GEOSException ('Could not parse version info string "%s"' % ver )
148
189
return {key : m .group (key ) for key in (
149
190
'version' , 'release_candidate' , 'capi_version' , 'major' , 'minor' , 'subminor' )}
150
-
151
- # Version numbers and whether or not prepared geometry support is available.
152
- _verinfo = geos_version_info ()
153
- GEOS_MAJOR_VERSION = int (_verinfo ['major' ])
154
- GEOS_MINOR_VERSION = int (_verinfo ['minor' ])
155
- GEOS_SUBMINOR_VERSION = int (_verinfo ['subminor' ])
156
- del _verinfo
157
- GEOS_VERSION = (GEOS_MAJOR_VERSION , GEOS_MINOR_VERSION , GEOS_SUBMINOR_VERSION )
158
-
159
- # Here we set up the prototypes for the initGEOS_r and finishGEOS_r
160
- # routines. These functions aren't actually called until they are
161
- # attached to a GEOS context handle -- this actually occurs in
162
- # geos/prototypes/threadsafe.py.
163
- lgeos .initGEOS_r .restype = CONTEXT_PTR
164
- lgeos .finishGEOS_r .argtypes = [CONTEXT_PTR ]
0 commit comments