You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

libgdal.py 3.5 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. from __future__ import unicode_literals
  2. import logging
  3. import os
  4. import re
  5. from ctypes import CDLL, CFUNCTYPE, c_char_p, c_int
  6. from ctypes.util import find_library
  7. from django.contrib.gis.gdal.error import GDALException
  8. from django.core.exceptions import ImproperlyConfigured
  9. logger = logging.getLogger('django.contrib.gis')
  10. # Custom library path set?
  11. try:
  12. from django.conf import settings
  13. lib_path = settings.GDAL_LIBRARY_PATH
  14. except (AttributeError, EnvironmentError,
  15. ImportError, ImproperlyConfigured):
  16. lib_path = None
  17. if lib_path:
  18. lib_names = None
  19. elif os.name == 'nt':
  20. # Windows NT shared libraries
  21. lib_names = ['gdal111', 'gdal110', 'gdal19', 'gdal18', 'gdal17']
  22. elif os.name == 'posix':
  23. # *NIX library names.
  24. lib_names = ['gdal', 'GDAL', 'gdal1.11.0', 'gdal1.10.0', 'gdal1.9.0',
  25. 'gdal1.8.0', 'gdal1.7.0']
  26. else:
  27. raise GDALException('Unsupported OS "%s"' % os.name)
  28. # Using the ctypes `find_library` utility to find the
  29. # path to the GDAL library from the list of library names.
  30. if lib_names:
  31. for lib_name in lib_names:
  32. lib_path = find_library(lib_name)
  33. if lib_path is not None:
  34. break
  35. if lib_path is None:
  36. raise GDALException('Could not find the GDAL library (tried "%s"). '
  37. 'Try setting GDAL_LIBRARY_PATH in your settings.' %
  38. '", "'.join(lib_names))
  39. # This loads the GDAL/OGR C library
  40. lgdal = CDLL(lib_path)
  41. # On Windows, the GDAL binaries have some OSR routines exported with
  42. # STDCALL, while others are not. Thus, the library will also need to
  43. # be loaded up as WinDLL for said OSR functions that require the
  44. # different calling convention.
  45. if os.name == 'nt':
  46. from ctypes import WinDLL
  47. lwingdal = WinDLL(lib_path)
  48. def std_call(func):
  49. """
  50. Returns the correct STDCALL function for certain OSR routines on Win32
  51. platforms.
  52. """
  53. if os.name == 'nt':
  54. return lwingdal[func]
  55. else:
  56. return lgdal[func]
  57. # #### Version-information functions. ####
  58. # Returns GDAL library version information with the given key.
  59. _version_info = std_call('GDALVersionInfo')
  60. _version_info.argtypes = [c_char_p]
  61. _version_info.restype = c_char_p
  62. def gdal_version():
  63. "Returns only the GDAL version number information."
  64. return _version_info(b'RELEASE_NAME')
  65. def gdal_full_version():
  66. "Returns the full GDAL version information."
  67. return _version_info('')
  68. version_regex = re.compile(r'^(?P<major>\d+)\.(?P<minor>\d+)(\.(?P<subminor>\d+))?')
  69. def gdal_version_info():
  70. ver = gdal_version().decode()
  71. m = version_regex.match(ver)
  72. if not m:
  73. raise GDALException('Could not parse GDAL version string "%s"' % ver)
  74. return {key: m.group(key) for key in ('major', 'minor', 'subminor')}
  75. _verinfo = gdal_version_info()
  76. GDAL_MAJOR_VERSION = int(_verinfo['major'])
  77. GDAL_MINOR_VERSION = int(_verinfo['minor'])
  78. GDAL_SUBMINOR_VERSION = _verinfo['subminor'] and int(_verinfo['subminor'])
  79. GDAL_VERSION = (GDAL_MAJOR_VERSION, GDAL_MINOR_VERSION, GDAL_SUBMINOR_VERSION)
  80. del _verinfo
  81. # Set library error handling so as errors are logged
  82. CPLErrorHandler = CFUNCTYPE(None, c_int, c_int, c_char_p)
  83. def err_handler(error_class, error_number, message):
  84. logger.error('GDAL_ERROR %d: %s' % (error_number, message))
  85. err_handler = CPLErrorHandler(err_handler)
  86. def function(name, args, restype):
  87. func = std_call(name)
  88. func.argtypes = args
  89. func.restype = restype
  90. return func
  91. set_error_handler = function('CPLSetErrorHandler', [CPLErrorHandler], CPLErrorHandler)
  92. set_error_handler(err_handler)