From 25f47bbbb66c4db9cb6a0a6325d6fef1da9001bf Mon Sep 17 00:00:00 2001
From: Justin Bronn <jbronn@gmail.com>
Date: Wed, 27 Jan 2010 03:32:30 +0000
Subject: [PATCH] Applied DRY and centralized geometry input regular
 expressions; `OGRGeometry` may now consume and output EWKT.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12302 bcc190cf-cafb-0310-a4f2-bffc1f526a37
---
 django/contrib/gis/gdal/geometries.py      | 26 +++++++++++++++-------
 django/contrib/gis/gdal/tests/test_geom.py | 11 +++++++++
 django/contrib/gis/geometry/regex.py       | 12 ++++++++++
 django/contrib/gis/geos/geometry.py        |  9 +++-----
 4 files changed, 44 insertions(+), 14 deletions(-)
 create mode 100644 django/contrib/gis/geometry/regex.py

diff --git a/django/contrib/gis/gdal/geometries.py b/django/contrib/gis/gdal/geometries.py
index b301cc1c27..df5ea70547 100644
--- a/django/contrib/gis/gdal/geometries.py
+++ b/django/contrib/gis/gdal/geometries.py
@@ -39,7 +39,7 @@
   True
 """
 # Python library requisites.
-import re, sys
+import sys
 from binascii import a2b_hex
 from ctypes import byref, string_at, c_char_p, c_double, c_ubyte, c_void_p
 
@@ -54,16 +54,14 @@ from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform
 from django.contrib.gis.gdal.prototypes import geom as capi, srs as srs_api
 GEOJSON = capi.GEOJSON
 
+# For recognizing geometry input.
+from django.contrib.gis.geometry.regex import hex_regex, wkt_regex, json_regex
+
 # For more information, see the OGR C API source code:
 #  http://www.gdal.org/ogr/ogr__api_8h.html
 #
 # The OGR_G_* routines are relevant here.
 
-# Regular expressions for recognizing HEXEWKB and WKT.
-hex_regex = re.compile(r'^[0-9A-F]+$', re.I)
-wkt_regex = re.compile(r'^(?P<type>POINT|LINESTRING|LINEARRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)[ACEGIMLONPSRUTY\d,\.\-\(\) ]+$', re.I)
-json_regex = re.compile(r'^(\s+)?\{[\s\w,\[\]\{\}\-\."\':]+\}(\s+)?$')
-
 #### OGRGeometry Class ####
 class OGRGeometry(GDALBase):
     "Generally encapsulates an OGR geometry."
@@ -88,13 +86,16 @@ class OGRGeometry(GDALBase):
             wkt_m = wkt_regex.match(geom_input)
             json_m = json_regex.match(geom_input)
             if wkt_m:
+                if wkt_m.group('srid'):
+                    # If there's EWKT, set the SRS w/value of the SRID.
+                    srs = int(wkt_m.group('srid'))
                 if wkt_m.group('type').upper() == 'LINEARRING':
                     # OGR_G_CreateFromWkt doesn't work with LINEARRING WKT.
                     #  See http://trac.osgeo.org/gdal/ticket/1992.
                     g = capi.create_geom(OGRGeomType(wkt_m.group('type')).num)
-                    capi.import_wkt(g, byref(c_char_p(geom_input)))
+                    capi.import_wkt(g, byref(c_char_p(wkt_m.group('wkt'))))
                 else:
-                    g = capi.from_wkt(byref(c_char_p(geom_input)), None, byref(c_void_p()))
+                    g = capi.from_wkt(byref(c_char_p(wkt_m.group('wkt'))), None, byref(c_void_p()))
             elif json_m:
                 if GEOJSON:
                     g = capi.from_json(geom_input)
@@ -341,6 +342,15 @@ class OGRGeometry(GDALBase):
         "Returns the WKT representation of the Geometry."
         return capi.to_wkt(self.ptr, byref(c_char_p()))
 
+    @property
+    def ewkt(self):
+        "Returns the EWKT representation of the Geometry."
+        srs = self.srs
+        if srs and srs.srid:
+            return 'SRID=%s;%s' % (srs.srid, self.wkt)
+        else:
+            return self.wkt
+
     #### Geometry Methods ####
     def clone(self):
         "Clones this OGR Geometry."
diff --git a/django/contrib/gis/gdal/tests/test_geom.py b/django/contrib/gis/gdal/tests/test_geom.py
index 02305f97b4..93f08504a1 100644
--- a/django/contrib/gis/gdal/tests/test_geom.py
+++ b/django/contrib/gis/gdal/tests/test_geom.py
@@ -59,6 +59,17 @@ class OGRGeomTest(unittest.TestCase):
             geom = OGRGeometry(g.wkt)
             self.assertEqual(g.wkt, geom.wkt)
 
+    def test01a_ewkt(self):
+        "Testing EWKT input/output."
+        for ewkt_val in ('POINT (1 2 3)', 'LINEARRING (0 0,1 1,2 1,0 0)'):
+            # First with ewkt output when no SRID in EWKT
+            self.assertEqual(ewkt_val, OGRGeometry(ewkt_val).ewkt)
+            # No test consumption with an SRID specified.
+            ewkt_val = 'SRID=4326;%s' % ewkt_val
+            geom = OGRGeometry(ewkt_val)
+            self.assertEqual(ewkt_val, geom.ewkt)
+            self.assertEqual(4326, geom.srs.srid)
+
     def test01b_gml(self):
         "Testing GML output."
         for g in wkt_out:
diff --git a/django/contrib/gis/geometry/regex.py b/django/contrib/gis/geometry/regex.py
new file mode 100644
index 0000000000..85238581bf
--- /dev/null
+++ b/django/contrib/gis/geometry/regex.py
@@ -0,0 +1,12 @@
+import re
+
+# Regular expression for recognizing HEXEWKB and WKT.  A prophylactic measure
+# to prevent potentially malicious input from reaching the underlying C
+# library.  Not a substitute for good web security programming practices.
+hex_regex = re.compile(r'^[0-9A-F]+$', re.I)
+wkt_regex = re.compile(r'^(SRID=(?P<srid>\d+);)?'
+                       r'(?P<wkt>'
+                       r'(?P<type>POINT|LINESTRING|LINEARRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)'
+                       r'[ACEGIMLONPSRUTYZ\d,\.\-\(\) ]+)$',
+                       re.I)
+json_regex = re.compile(r'^(\s+)?\{[\s\w,\[\]\{\}\-\."\':]+\}(\s+)?$')
diff --git a/django/contrib/gis/geos/geometry.py b/django/contrib/gis/geos/geometry.py
index 84b0454921..c508431c2a 100644
--- a/django/contrib/gis/geos/geometry.py
+++ b/django/contrib/gis/geos/geometry.py
@@ -25,11 +25,8 @@ from django.contrib.gis.geos import prototypes as capi
 # of their corresponding GEOS I/O class.
 from django.contrib.gis.geos.prototypes.io import wkt_r, wkt_w, wkb_r, wkb_w, ewkb_w, ewkb_w3d
 
-# Regular expression for recognizing HEXEWKB and WKT.  A prophylactic measure
-# to prevent potentially malicious input from reaching the underlying C
-# library.  Not a substitute for good web security programming practices.
-hex_regex = re.compile(r'^[0-9A-F]+$', re.I)
-wkt_regex = re.compile(r'^(SRID=(?P<srid>\d+);)?(?P<wkt>(POINT|LINESTRING|LINEARRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)[ACEGIMLONPSRUTY\d,\.\-\(\) ]+)$', re.I)
+# For recognizing geometry input.
+from django.contrib.gis.geometry.regex import hex_regex, wkt_regex, json_regex
 
 class GEOSGeometry(GEOSBase, ListMixin):
     "A class that, generally, encapsulates a GEOS geometry."
@@ -69,7 +66,7 @@ class GEOSGeometry(GEOSBase, ListMixin):
             elif hex_regex.match(geo_input):
                 # Handling HEXEWKB input.
                 g = wkb_r().read(geo_input)
-            elif gdal.GEOJSON and gdal.geometries.json_regex.match(geo_input):
+            elif gdal.GEOJSON and json_regex.match(geo_input):
                 # Handling GeoJSON input.
                 g = wkb_r().read(gdal.OGRGeometry(geo_input).wkb)
             else: