text: from unittest import skipUnless
  
  from django.forms import ValidationError
  from django.contrib.gis.gdal import HAS_GDAL
  from django.contrib.gis.tests.utils import HAS_SPATIALREFSYS
  from django.test import SimpleTestCase
  from django.utils import six
  from django.utils.html import escape
  
  if HAS_SPATIALREFSYS:
      from django.contrib.gis import forms
      from django.contrib.gis.geos import GEOSGeometry
  
  
  @skipUnless(HAS_GDAL and HAS_SPATIALREFSYS, "GeometryFieldTest needs gdal support and a spatial database")
  class GeometryFieldTest(SimpleTestCase):
  
      def test_init(self):
          "Testing GeometryField initialization with defaults."
          fld = forms.GeometryField()
          for bad_default in ('blah', 3, 'FoO', None, 0):
              self.assertRaises(ValidationError, fld.clean, bad_default)
  
      def test_srid(self):
          "Testing GeometryField with a SRID set."
          # Input that doesn't specify the SRID is assumed to be in the SRID
          # of the input field.
          fld = forms.GeometryField(srid=4326)
          geom = fld.clean('POINT(5 23)')
          self.assertEqual(4326, geom.srid)
          # Making the field in a different SRID from that of the geometry, and
          # asserting it transforms.
          fld = forms.GeometryField(srid=32140)
          tol = 0.0000001
          xform_geom = GEOSGeometry('POINT (951640.547328465 4219369.26171664)', srid=32140)
          # The cleaned geometry should be transformed to 32140.
          cleaned_geom = fld.clean('SRID=4326;POINT (-95.363151 29.763374)')
          self.assertTrue(xform_geom.equals_exact(cleaned_geom, tol))
  
      def test_null(self):
          "Testing GeometryField's handling of null (None) geometries."
          # Form fields, by default, are required (`required=True`)
          fld = forms.GeometryField()
          with six.assertRaisesRegex(self, forms.ValidationError,
                  "No geometry value provided."):
              fld.clean(None)
  
          # This will clean None as a geometry (See #10660).
          fld = forms.GeometryField(required=False)
          self.assertIsNone(fld.clean(None))
  
      def test_geom_type(self):
          "Testing GeometryField's handling of different geometry types."
          # By default, all geometry types are allowed.
          fld = forms.GeometryField()
          for wkt in ('POINT(5 23)', 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))', 'LINESTRING(0 0, 1 1)'):
              self.assertEqual(GEOSGeometry(wkt), fld.clean(wkt))
  
          pnt_fld = forms.GeometryField(geom_type='POINT')
          self.assertEqual(GEOSGeometry('POINT(5 23)'), pnt_fld.clean('POINT(5 23)'))
          # a WKT for any other geom_type will be properly transformed by `to_python`
          self.assertEqual(GEOSGeometry('LINESTRING(0 0, 1 1)'), pnt_fld.to_python('LINESTRING(0 0, 1 1)'))
          # but rejected by `clean`
          self.assertRaises(forms.ValidationError, pnt_fld.clean, 'LINESTRING(0 0, 1 1)')
  
      def test_to_python(self):
          """
          Testing to_python returns a correct GEOSGeometry object or
          a ValidationError
          """
          fld = forms.GeometryField()
          # to_python returns the same GEOSGeometry for a WKT
          for wkt in ('POINT(5 23)', 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))', 'LINESTRING(0 0, 1 1)'):
              self.assertEqual(GEOSGeometry(wkt), fld.to_python(wkt))
          # but raises a ValidationError for any other string
          for wkt in ('POINT(5)', 'MULTI   POLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))', 'BLAH(0 0, 1 1)'):
              self.assertRaises(forms.ValidationError, fld.to_python, wkt)
  
      def test_field_with_text_widget(self):
          class PointForm(forms.Form):
              pt = forms.PointField(srid=4326, widget=forms.TextInput)
  
          form = PointForm()
          cleaned_pt = form.fields['pt'].clean('POINT(5 23)')
          self.assertEqual(cleaned_pt, GEOSGeometry('POINT(5 23)'))
          self.assertEqual(4326, cleaned_pt.srid)
  
          point = GEOSGeometry('SRID=4326;POINT(5 23)')
          form = PointForm(data={'pt': 'POINT(5 23)'}, initial={'pt': point})
          self.assertFalse(form.has_changed())
  
  
  @skipUnless(HAS_GDAL and HAS_SPATIALREFSYS,
      "SpecializedFieldTest needs gdal support and a spatial database")
  class SpecializedFieldTest(SimpleTestCase):
      def setUp(self):
          self.geometries = {
              'point': GEOSGeometry("SRID=4326;POINT(9.052734375 42.451171875)"),
              'multipoint': GEOSGeometry("SRID=4326;MULTIPOINT("
                                         "(13.18634033203125 14.504356384277344),"
                                         "(13.207969665527 14.490966796875),"
                                         "(13.177070617675 14.454917907714))"),
              'linestring': GEOSGeometry("SRID=4326;LINESTRING("
                                         "-8.26171875 -0.52734375,"
                                         "-7.734375 4.21875,"
                                         "6.85546875 3.779296875,"
                                         "5.44921875 -3.515625)"),
              'multilinestring': GEOSGeometry("SRID=4326;MULTILINESTRING("
                                              "(-16.435546875 -2.98828125,"
                                              "-17.2265625 2.98828125,"
                                              "-0.703125 3.515625,"
                                              "-1.494140625 -3.33984375),"
                                              "(-8.0859375 -5.9765625,"
                                              "8.525390625 -8.7890625,"
                                              "12.392578125 -0.87890625,"
                                              "10.01953125 7.646484375))"),
              'polygon': GEOSGeometry("SRID=4326;POLYGON("
                                      "(-1.669921875 6.240234375,"
                                      "-3.8671875 -0.615234375,"
                                      "5.9765625 -3.955078125,"
                                      "18.193359375 3.955078125,"
                                      "9.84375 9.4921875,"
                                      "-1.669921875 6.240234375))"),
              'multipolygon': GEOSGeometry("SRID=4326;MULTIPOLYGON("
                                           "((-17.578125 13.095703125,"
                                           "-17.2265625 10.8984375,"
                                           "-13.974609375 10.1953125,"
                                           "-13.359375 12.744140625,"
                                           "-15.732421875 13.7109375,"
                                           "-17.578125 13.095703125)),"
                                           "((-8.525390625 5.537109375,"
                                           "-8.876953125 2.548828125,"
                                           "-5.888671875 1.93359375,"
                                           "-5.09765625 4.21875,"
                                           "-6.064453125 6.240234375,"
                                           "-8.525390625 5.537109375)))"),
              'geometrycollection': GEOSGeometry("SRID=4326;GEOMETRYCOLLECTION("
                                                 "POINT(5.625 -0.263671875),"
                                                 "POINT(6.767578125 -3.603515625),"
                                                 "POINT(8.525390625 0.087890625),"
                                                 "POINT(8.0859375 -2.13134765625),"
                                                 "LINESTRING("
                                                 "6.273193359375 -1.175537109375,"
                                                 "5.77880859375 -1.812744140625,"
                                                 "7.27294921875 -2.230224609375,"
                                                 "7.657470703125 -1.25244140625))"),
          }
  
      def assertMapWidget(self, form_instance):
          """
          Make sure the MapWidget js is passed in the form media and a MapWidget
          is actually created
          """
          self.assertTrue(form_instance.is_valid())
          rendered = form_instance.as_p()
          self.assertIn('new MapWidget(options);', rendered)
          self.assertIn('gis/js/OLMapWidget.js', str(form_instance.media))
  
      def assertTextarea(self, geom, rendered):
          """Makes sure the wkt and a textarea are in the content"""
  
          self.assertIn('<textarea ', rendered)
          self.assertIn('required', rendered)
          self.assertIn(geom.wkt, rendered)
  
      def test_pointfield(self):
          class PointForm(forms.Form):
              p = forms.PointField()
  
          geom = self.geometries['point']
          form = PointForm(data={'p': geom})
          self.assertTextarea(geom, form.as_p())
          self.assertMapWidget(form)
          self.assertFalse(PointForm().is_valid())
          invalid = PointForm(data={'p': 'some invalid geom'})
          self.assertFalse(invalid.is_valid())
          self.assertTrue('Invalid geometry value' in str(invalid.errors))
  
          for invalid in [geo for key, geo in self.geometries.items() if key != 'point']:
              self.assertFalse(PointForm(data={'p': invalid.wkt}).is_valid())
  
      def test_multipointfield(self):
          class PointForm(forms.Form):
              p = forms.MultiPointField()
  
          geom = self.geometries['multipoint']
          form = PointForm(data={'p': geom})
          self.assertTextarea(geom, form.as_p())
          self.assertMapWidget(form)
          self.assertFalse(PointForm().is_valid())
  
          for invalid in [geo for key, geo in self.geometries.items() if key != 'multipoint']:
              self.assertFalse(PointForm(data={'p': invalid.wkt}).is_valid())
  
      def test_linestringfield(self):
          class LineStringForm(forms.Form):
              l = forms.LineStringField()
  
          geom = self.geometries['linestring']
          form = LineStringForm(data={'l': geom})
          self.assertTextarea(geom, form.as_p())
          self.assertMapWidget(form)
          self.assertFalse(LineStringForm().is_valid())
  
          for invalid in [geo for key, geo in self.geometries.items() if key != 'linestring']:
              self.assertFalse(LineStringForm(data={'p': invalid.wkt}).is_valid())
  
      def test_multilinestringfield(self):
          class LineStringForm(forms.Form):
              l = forms.MultiLineStringField()
  
          geom = self.geometries['multilinestring']
          form = LineStringForm(data={'l': geom})
          self.assertTextarea(geom, form.as_p())
          self.assertMapWidget(form)
          self.assertFalse(LineStringForm().is_valid())
  
          for invalid in [geo for key, geo in self.geometries.items() if key != 'multilinestring']:
              self.assertFalse(LineStringForm(data={'p': invalid.wkt}).is_valid())
  
      def test_polygonfield(self):
          class PolygonForm(forms.Form):
              p = forms.PolygonField()
  
          geom = self.geometries['polygon']
          form = PolygonForm(data={'p': geom})
          self.assertTextarea(geom, form.as_p())
          self.assertMapWidget(form)
          self.assertFalse(PolygonForm().is_valid())
  
          for invalid in [geo for key, geo in self.geometries.items() if key != 'polygon']:
              self.assertFalse(PolygonForm(data={'p': invalid.wkt}).is_valid())
  
      def test_multipolygonfield(self):
          class PolygonForm(forms.Form):
              p = forms.MultiPolygonField()
  
          geom = self.geometries['multipolygon']
          form = PolygonForm(data={'p': geom})
          self.assertTextarea(geom, form.as_p())
          self.assertMapWidget(form)
          self.assertFalse(PolygonForm().is_valid())
  
          for invalid in [geo for key, geo in self.geometries.items() if key != 'multipolygon']:
              self.assertFalse(PolygonForm(data={'p': invalid.wkt}).is_valid())
  
      def test_geometrycollectionfield(self):
          class GeometryForm(forms.Form):
              g = forms.GeometryCollectionField()
  
          geom = self.geometries['geometrycollection']
          form = GeometryForm(data={'g': geom})
          self.assertTextarea(geom, form.as_p())
          self.assertMapWidget(form)
          self.assertFalse(GeometryForm().is_valid())
  
          for invalid in [geo for key, geo in self.geometries.items() if key != 'geometrycollection']:
              self.assertFalse(GeometryForm(data={'g': invalid.wkt}).is_valid())
  
  
  @skipUnless(HAS_GDAL and HAS_SPATIALREFSYS,
      "OSMWidgetTest needs gdal support and a spatial database")
  class OSMWidgetTest(SimpleTestCase):
      def setUp(self):
          self.geometries = {
              'point': GEOSGeometry("SRID=4326;POINT(9.052734375 42.451171875)"),
          }
  
      def test_osm_widget(self):
          class PointForm(forms.Form):
              p = forms.PointField(widget=forms.OSMWidget)
  
          geom = self.geometries['point']
          form = PointForm(data={'p': geom})
          rendered = form.as_p()
  
          self.assertIn("OpenStreetMap (Mapnik)", rendered)
          self.assertIn("id: 'id_p',", rendered)
  
      def test_default_lat_lon(self):
          class PointForm(forms.Form):
              p = forms.PointField(
                  widget=forms.OSMWidget(attrs={
                      'default_lon': 20, 'default_lat': 30
                  }),
              )
  
          form = PointForm()
          rendered = form.as_p()
  
          self.assertIn("options['default_lon'] = 20;", rendered)
          self.assertIn("options['default_lat'] = 30;", rendered)
          if forms.OSMWidget.default_lon != 20:
              self.assertNotIn(
                  "options['default_lon'] = %d;" % forms.OSMWidget.default_lon,
                  rendered)
          if forms.OSMWidget.default_lat != 30:
              self.assertNotIn(
                  "options['default_lat'] = %d;" % forms.OSMWidget.default_lat,
                  rendered)
  
  
  @skipUnless(HAS_GDAL and HAS_SPATIALREFSYS,
      "CustomGeometryWidgetTest needs gdal support and a spatial database")
  class CustomGeometryWidgetTest(SimpleTestCase):
  
      def test_custom_serialization_widget(self):
          class CustomGeometryWidget(forms.BaseGeometryWidget):
              template_name = 'gis/openlayers.html'
              deserialize_called = 0
  
              def serialize(self, value):
                  return value.json if value else ''
  
              def deserialize(self, value):
                  self.deserialize_called += 1
                  return GEOSGeometry(value)
  
          class PointForm(forms.Form):
              p = forms.PointField(widget=CustomGeometryWidget)
  
          point = GEOSGeometry("SRID=4326;POINT(9.052734375 42.451171875)")
          form = PointForm(data={'p': point})
          self.assertIn(escape(point.json), form.as_p())
  
          CustomGeometryWidget.called = 0
          widget = form.fields['p'].widget
          # Force deserialize use due to a string value
          self.assertIn(escape(point.json), widget.render('p', point.json))
          self.assertEqual(widget.deserialize_called, 1)
  
          form = PointForm(data={'p': point.json})
          self.assertTrue(form.is_valid())
          # Ensure that resulting geometry has srid set
          self.assertEqual(form.cleaned_data['p'].srid, 4326)
  