/django/contrib/gis/gdal/field.py

https://code.google.com/p/mango-py/ · Python · 186 lines · 128 code · 26 blank · 32 comment · 15 complexity · 1c97e6b9e0cd031036ba9cf75e5e4eea MD5 · raw file

  1. from ctypes import byref, c_int
  2. from datetime import date, datetime, time
  3. from django.contrib.gis.gdal.base import GDALBase
  4. from django.contrib.gis.gdal.error import OGRException
  5. from django.contrib.gis.gdal.prototypes import ds as capi
  6. # For more information, see the OGR C API source code:
  7. # http://www.gdal.org/ogr/ogr__api_8h.html
  8. #
  9. # The OGR_Fld_* routines are relevant here.
  10. class Field(GDALBase):
  11. "A class that wraps an OGR Field, needs to be instantiated from a Feature object."
  12. #### Python 'magic' routines ####
  13. def __init__(self, feat, index):
  14. """
  15. Initializes on the feature pointer and the integer index of
  16. the field within the feature.
  17. """
  18. # Setting the feature pointer and index.
  19. self._feat = feat
  20. self._index = index
  21. # Getting the pointer for this field.
  22. fld_ptr = capi.get_feat_field_defn(feat, index)
  23. if not fld_ptr:
  24. raise OGRException('Cannot create OGR Field, invalid pointer given.')
  25. self.ptr = fld_ptr
  26. # Setting the class depending upon the OGR Field Type (OFT)
  27. self.__class__ = OGRFieldTypes[self.type]
  28. # OFTReal with no precision should be an OFTInteger.
  29. if isinstance(self, OFTReal) and self.precision == 0:
  30. self.__class__ = OFTInteger
  31. self._double = True
  32. def __str__(self):
  33. "Returns the string representation of the Field."
  34. return str(self.value).strip()
  35. #### Field Methods ####
  36. def as_double(self):
  37. "Retrieves the Field's value as a double (float)."
  38. return capi.get_field_as_double(self._feat, self._index)
  39. def as_int(self):
  40. "Retrieves the Field's value as an integer."
  41. return capi.get_field_as_integer(self._feat, self._index)
  42. def as_string(self):
  43. "Retrieves the Field's value as a string."
  44. return capi.get_field_as_string(self._feat, self._index)
  45. def as_datetime(self):
  46. "Retrieves the Field's value as a tuple of date & time components."
  47. yy, mm, dd, hh, mn, ss, tz = [c_int() for i in range(7)]
  48. status = capi.get_field_as_datetime(self._feat, self._index, byref(yy), byref(mm), byref(dd),
  49. byref(hh), byref(mn), byref(ss), byref(tz))
  50. if status:
  51. return (yy, mm, dd, hh, mn, ss, tz)
  52. else:
  53. raise OGRException('Unable to retrieve date & time information from the field.')
  54. #### Field Properties ####
  55. @property
  56. def name(self):
  57. "Returns the name of this Field."
  58. return capi.get_field_name(self.ptr)
  59. @property
  60. def precision(self):
  61. "Returns the precision of this Field."
  62. return capi.get_field_precision(self.ptr)
  63. @property
  64. def type(self):
  65. "Returns the OGR type of this Field."
  66. return capi.get_field_type(self.ptr)
  67. @property
  68. def type_name(self):
  69. "Return the OGR field type name for this Field."
  70. return capi.get_field_type_name(self.type)
  71. @property
  72. def value(self):
  73. "Returns the value of this Field."
  74. # Default is to get the field as a string.
  75. return self.as_string()
  76. @property
  77. def width(self):
  78. "Returns the width of this Field."
  79. return capi.get_field_width(self.ptr)
  80. ### The Field sub-classes for each OGR Field type. ###
  81. class OFTInteger(Field):
  82. _double = False
  83. @property
  84. def value(self):
  85. "Returns an integer contained in this field."
  86. if self._double:
  87. # If this is really from an OFTReal field with no precision,
  88. # read as a double and cast as Python int (to prevent overflow).
  89. return int(self.as_double())
  90. else:
  91. return self.as_int()
  92. @property
  93. def type(self):
  94. """
  95. GDAL uses OFTReals to represent OFTIntegers in created
  96. shapefiles -- forcing the type here since the underlying field
  97. type may actually be OFTReal.
  98. """
  99. return 0
  100. class OFTReal(Field):
  101. @property
  102. def value(self):
  103. "Returns a float contained in this field."
  104. return self.as_double()
  105. # String & Binary fields, just subclasses
  106. class OFTString(Field): pass
  107. class OFTWideString(Field): pass
  108. class OFTBinary(Field): pass
  109. # OFTDate, OFTTime, OFTDateTime fields.
  110. class OFTDate(Field):
  111. @property
  112. def value(self):
  113. "Returns a Python `date` object for the OFTDate field."
  114. try:
  115. yy, mm, dd, hh, mn, ss, tz = self.as_datetime()
  116. return date(yy.value, mm.value, dd.value)
  117. except (ValueError, OGRException):
  118. return None
  119. class OFTDateTime(Field):
  120. @property
  121. def value(self):
  122. "Returns a Python `datetime` object for this OFTDateTime field."
  123. # TODO: Adapt timezone information.
  124. # See http://lists.maptools.org/pipermail/gdal-dev/2006-February/007990.html
  125. # The `tz` variable has values of: 0=unknown, 1=localtime (ambiguous),
  126. # 100=GMT, 104=GMT+1, 80=GMT-5, etc.
  127. try:
  128. yy, mm, dd, hh, mn, ss, tz = self.as_datetime()
  129. return datetime(yy.value, mm.value, dd.value, hh.value, mn.value, ss.value)
  130. except (ValueError, OGRException):
  131. return None
  132. class OFTTime(Field):
  133. @property
  134. def value(self):
  135. "Returns a Python `time` object for this OFTTime field."
  136. try:
  137. yy, mm, dd, hh, mn, ss, tz = self.as_datetime()
  138. return time(hh.value, mn.value, ss.value)
  139. except (ValueError, OGRException):
  140. return None
  141. # List fields are also just subclasses
  142. class OFTIntegerList(Field): pass
  143. class OFTRealList(Field): pass
  144. class OFTStringList(Field): pass
  145. class OFTWideStringList(Field): pass
  146. # Class mapping dictionary for OFT Types and reverse mapping.
  147. OGRFieldTypes = { 0 : OFTInteger,
  148. 1 : OFTIntegerList,
  149. 2 : OFTReal,
  150. 3 : OFTRealList,
  151. 4 : OFTString,
  152. 5 : OFTStringList,
  153. 6 : OFTWideString,
  154. 7 : OFTWideStringList,
  155. 8 : OFTBinary,
  156. 9 : OFTDate,
  157. 10 : OFTTime,
  158. 11 : OFTDateTime,
  159. }
  160. ROGRFieldTypes = dict([(cls, num) for num, cls in OGRFieldTypes.items()])