2012-09-24 01:59:27 +08:00
|
|
|
from __future__ import unicode_literals
|
|
|
|
|
2012-10-05 04:41:03 +08:00
|
|
|
import logging
|
2011-07-13 17:35:51 +08:00
|
|
|
import os
|
|
|
|
import re
|
2012-10-05 04:41:03 +08:00
|
|
|
from ctypes import c_char_p, c_int, CDLL, CFUNCTYPE
|
2008-08-06 02:13:06 +08:00
|
|
|
from ctypes.util import find_library
|
2012-10-05 04:41:03 +08:00
|
|
|
|
2008-08-06 02:13:06 +08:00
|
|
|
from django.contrib.gis.gdal.error import OGRException
|
2012-10-06 05:38:01 +08:00
|
|
|
from django.core.exceptions import ImproperlyConfigured
|
2012-10-05 04:41:03 +08:00
|
|
|
|
|
|
|
logger = logging.getLogger('django.contrib.gis')
|
|
|
|
|
2008-08-06 02:13:06 +08:00
|
|
|
# Custom library path set?
|
|
|
|
try:
|
|
|
|
from django.conf import settings
|
|
|
|
lib_path = settings.GDAL_LIBRARY_PATH
|
2012-10-06 05:38:01 +08:00
|
|
|
except (AttributeError, EnvironmentError,
|
|
|
|
ImportError, ImproperlyConfigured):
|
2008-08-06 02:13:06 +08:00
|
|
|
lib_path = None
|
|
|
|
|
|
|
|
if lib_path:
|
|
|
|
lib_names = None
|
|
|
|
elif os.name == 'nt':
|
2011-03-16 12:44:26 +08:00
|
|
|
# Windows NT shared libraries
|
2014-07-22 01:02:25 +08:00
|
|
|
lib_names = ['gdal111', 'gdal110', 'gdal19', 'gdal18', 'gdal17']
|
2008-08-06 02:13:06 +08:00
|
|
|
elif os.name == 'posix':
|
|
|
|
# *NIX library names.
|
2014-07-22 01:02:25 +08:00
|
|
|
lib_names = ['gdal', 'GDAL', 'gdal1.11.0', 'gdal1.10.0', 'gdal1.9.0',
|
|
|
|
'gdal1.8.0', 'gdal1.7.0']
|
2008-08-06 02:13:06 +08:00
|
|
|
else:
|
|
|
|
raise OGRException('Unsupported OS "%s"' % os.name)
|
|
|
|
|
2012-06-11 05:59:50 +08:00
|
|
|
# Using the ctypes `find_library` utility to find the
|
2008-08-06 02:13:06 +08:00
|
|
|
# path to the GDAL library from the list of library names.
|
|
|
|
if lib_names:
|
|
|
|
for lib_name in lib_names:
|
|
|
|
lib_path = find_library(lib_name)
|
2014-03-31 03:11:05 +08:00
|
|
|
if lib_path is not None:
|
2013-10-17 16:17:41 +08:00
|
|
|
break
|
2012-06-11 05:59:50 +08:00
|
|
|
|
2008-08-06 02:13:06 +08:00
|
|
|
if lib_path is None:
|
|
|
|
raise OGRException('Could not find the GDAL library (tried "%s"). '
|
2012-06-11 05:59:50 +08:00
|
|
|
'Try setting GDAL_LIBRARY_PATH in your settings.' %
|
2008-08-06 02:13:06 +08:00
|
|
|
'", "'.join(lib_names))
|
|
|
|
|
|
|
|
# This loads the GDAL/OGR C library
|
|
|
|
lgdal = CDLL(lib_path)
|
|
|
|
|
2012-06-11 05:59:50 +08:00
|
|
|
# On Windows, the GDAL binaries have some OSR routines exported with
|
|
|
|
# STDCALL, while others are not. Thus, the library will also need to
|
|
|
|
# be loaded up as WinDLL for said OSR functions that require the
|
2008-08-06 02:13:06 +08:00
|
|
|
# different calling convention.
|
|
|
|
if os.name == 'nt':
|
|
|
|
from ctypes import WinDLL
|
2008-09-16 01:25:17 +08:00
|
|
|
lwingdal = WinDLL(lib_path)
|
2008-08-06 02:13:06 +08:00
|
|
|
|
2013-11-03 04:12:09 +08:00
|
|
|
|
2008-08-06 02:13:06 +08:00
|
|
|
def std_call(func):
|
|
|
|
"""
|
|
|
|
Returns the correct STDCALL function for certain OSR routines on Win32
|
|
|
|
platforms.
|
|
|
|
"""
|
|
|
|
if os.name == 'nt':
|
|
|
|
return lwingdal[func]
|
|
|
|
else:
|
|
|
|
return lgdal[func]
|
|
|
|
|
|
|
|
#### Version-information functions. ####
|
|
|
|
|
|
|
|
# Returns GDAL library version information with the given key.
|
|
|
|
_version_info = std_call('GDALVersionInfo')
|
|
|
|
_version_info.argtypes = [c_char_p]
|
|
|
|
_version_info.restype = c_char_p
|
|
|
|
|
2013-11-03 04:12:09 +08:00
|
|
|
|
2008-08-06 02:13:06 +08:00
|
|
|
def gdal_version():
|
|
|
|
"Returns only the GDAL version number information."
|
2012-09-24 01:59:27 +08:00
|
|
|
return _version_info(b'RELEASE_NAME')
|
2008-08-06 02:13:06 +08:00
|
|
|
|
2013-11-03 04:12:09 +08:00
|
|
|
|
2012-06-11 05:59:50 +08:00
|
|
|
def gdal_full_version():
|
2008-08-06 02:13:06 +08:00
|
|
|
"Returns the full GDAL version information."
|
|
|
|
return _version_info('')
|
|
|
|
|
2010-03-26 04:00:27 +08:00
|
|
|
version_regex = re.compile(r'^(?P<major>\d+)\.(?P<minor>\d+)(\.(?P<subminor>\d+))?')
|
2013-11-03 04:12:09 +08:00
|
|
|
|
|
|
|
|
2010-03-26 04:00:27 +08:00
|
|
|
def gdal_version_info():
|
2012-09-24 01:59:27 +08:00
|
|
|
ver = gdal_version().decode()
|
2010-03-26 04:00:27 +08:00
|
|
|
m = version_regex.match(ver)
|
2013-10-17 16:17:41 +08:00
|
|
|
if not m:
|
|
|
|
raise OGRException('Could not parse GDAL version string "%s"' % ver)
|
2013-08-30 00:09:35 +08:00
|
|
|
return dict((key, m.group(key)) for key in ('major', 'minor', 'subminor'))
|
2010-03-26 04:00:27 +08:00
|
|
|
|
|
|
|
_verinfo = gdal_version_info()
|
|
|
|
GDAL_MAJOR_VERSION = int(_verinfo['major'])
|
|
|
|
GDAL_MINOR_VERSION = int(_verinfo['minor'])
|
|
|
|
GDAL_SUBMINOR_VERSION = _verinfo['subminor'] and int(_verinfo['subminor'])
|
|
|
|
GDAL_VERSION = (GDAL_MAJOR_VERSION, GDAL_MINOR_VERSION, GDAL_SUBMINOR_VERSION)
|
|
|
|
del _verinfo
|
2012-10-05 04:41:03 +08:00
|
|
|
|
|
|
|
# Set library error handling so as errors are logged
|
|
|
|
CPLErrorHandler = CFUNCTYPE(None, c_int, c_int, c_char_p)
|
2013-11-03 04:12:09 +08:00
|
|
|
|
|
|
|
|
2012-10-05 04:41:03 +08:00
|
|
|
def err_handler(error_class, error_number, message):
|
|
|
|
logger.error('GDAL_ERROR %d: %s' % (error_number, message))
|
|
|
|
err_handler = CPLErrorHandler(err_handler)
|
|
|
|
|
2013-11-03 04:12:09 +08:00
|
|
|
|
2012-10-05 04:41:03 +08:00
|
|
|
def function(name, args, restype):
|
|
|
|
func = std_call(name)
|
|
|
|
func.argtypes = args
|
|
|
|
func.restype = restype
|
|
|
|
return func
|
|
|
|
|
|
|
|
set_error_handler = function('CPLSetErrorHandler', [CPLErrorHandler], CPLErrorHandler)
|
|
|
|
set_error_handler(err_handler)
|