Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 17 additions & 25 deletions django/contrib/gis/db/backends/base/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.contrib.gis import gdal
from django.utils.functional import cached_property


class SpatialRefSysMixin:
Expand All @@ -7,35 +8,26 @@ class SpatialRefSysMixin:
SpatialRefSys objects to reduce redundant code.
"""

@property
@cached_property
def srs(self):
"""
Return a GDAL SpatialReference object.
"""
# TODO: Is caching really necessary here? Is complexity worth it?
if hasattr(self, "_srs"):
# Returning a clone of the cached SpatialReference object.
return self._srs.clone()
else:
# Attempting to cache a SpatialReference object.

# Trying to get from WKT first.
try:
self._srs = gdal.SpatialReference(self.wkt)
return self.srs
except Exception as e:
msg = e

try:
self._srs = gdal.SpatialReference(self.proj4text)
return self.srs
except Exception as e:
msg = e

raise Exception(
"Could not get OSR SpatialReference from WKT: %s\nError:\n%s"
% (self.wkt, msg)
)
try:
return gdal.SpatialReference(self.wkt)
except Exception as e:
wkt_error = e

try:
return gdal.SpatialReference(self.proj4text)
except Exception as e:
proj4_error = e

raise Exception(
"Could not get OSR SpatialReference.\n"
f"Error for WKT '{self.wkt}': {wkt_error}\n"
f"Error for PROJ.4 '{self.proj4text}': {proj4_error}"
)

@property
def ellipsoid(self):
Expand Down
15 changes: 15 additions & 0 deletions tests/gis_tests/test_spatialrefsys.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import re

from django.contrib.gis.db.backends.base.models import SpatialRefSysMixin
from django.db import connection
from django.test import TestCase, skipUnlessDBFeature
from django.utils.functional import cached_property
Expand Down Expand Up @@ -147,3 +148,17 @@ def test_add_entry(self):
self.assertTrue(
self.SpatialRefSys.get_spheroid(srs.wkt).startswith("SPHEROID[")
)

def test_srs_with_invalid_wkt_and_proj4(self):
class MockSpatialRefSys(SpatialRefSysMixin):
def __init__(self, wkt=None, proj4text=None):
self.wkt = wkt
self.proj4text = proj4text

with self.assertRaisesMessage(
Exception,
"Could not get OSR SpatialReference.\n"
"Error for WKT 'INVALID_WKT': Corrupt data.\n"
"Error for PROJ.4 '+proj=invalid': Corrupt data.",
):
MockSpatialRefSys(wkt="INVALID_WKT", proj4text="+proj=invalid").srs