From 229fc793a027f1fd3e6e9d553ed09c15b521776c Mon Sep 17 00:00:00 2001 From: Sergey Fedoseev Date: Mon, 23 Nov 2015 10:19:06 +0500 Subject: [PATCH] Refs #25663 -- Fixed checking of the number of points for LineString if initialized from numpy.array. --- django/contrib/gis/geos/linestring.py | 27 +++++++++++++------------ tests/gis_tests/geos_tests/test_geos.py | 24 ++++++++++++++++------ 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/django/contrib/gis/geos/linestring.py b/django/contrib/gis/geos/linestring.py index 7b74f7700a..d0edd631ce 100644 --- a/django/contrib/gis/geos/linestring.py +++ b/django/contrib/gis/geos/linestring.py @@ -32,18 +32,22 @@ class LineString(ProjectInterpolateMixin, GEOSGeometry): else: coords = args + if not (isinstance(coords, (tuple, list)) or numpy and isinstance(coords, numpy.ndarray)): + raise TypeError('Invalid initialization input for LineStrings.') + + ncoords = len(coords) + if ncoords < self._minlength: + raise ValueError( + '%s requires at least %d points, got %s.' % ( + self.__class__.__name__, + self._minlength, + ncoords, + ) + ) + if isinstance(coords, (tuple, list)): # Getting the number of coords and the number of dimensions -- which # must stay the same, e.g., no LineString((1, 2), (1, 2, 3)). - ncoords = len(coords) - if ncoords < self._minlength: - raise TypeError( - '%s requires at least %d points, got %s.' % ( - self.__class__.__name__, - self._minlength, - ncoords, - ) - ) ndim = None # Incrementing through each of the coordinates and verifying for coord in coords: @@ -56,16 +60,13 @@ class LineString(ProjectInterpolateMixin, GEOSGeometry): elif len(coord) != ndim: raise TypeError('Dimension mismatch.') numpy_coords = False - elif numpy and isinstance(coords, numpy.ndarray): + else: shape = coords.shape # Using numpy's shape. if len(shape) != 2: raise TypeError('Too many dimensions.') self._checkdim(shape[1]) - ncoords = shape[0] ndim = shape[1] numpy_coords = True - else: - raise TypeError('Invalid initialization input for LineStrings.') # Creating a coordinate sequence object because it is easier to # set the points using GEOSCoordSeq.__setitem__(). diff --git a/tests/gis_tests/geos_tests/test_geos.py b/tests/gis_tests/geos_tests/test_geos.py index 301d406317..33cc7dea4a 100644 --- a/tests/gis_tests/geos_tests/test_geos.py +++ b/tests/gis_tests/geos_tests/test_geos.py @@ -325,11 +325,19 @@ class GEOSTest(SimpleTestCase, TestDataMixin): if numpy: self.assertEqual(ls, LineString(numpy.array(ls.tuple))) # as numpy array - with self.assertRaisesMessage(TypeError, 'Each coordinate should be a sequence (list or tuple)'): - LineString((0, 0)) + with self.assertRaisesMessage(TypeError, 'Each coordinate should be a sequence (list or tuple)'): + LineString((0, 0)) - with self.assertRaisesMessage(TypeError, 'LineString requires at least 2 points, got 1.'): - LineString([(0, 0)]) + with self.assertRaisesMessage(ValueError, 'LineString requires at least 2 points, got 1.'): + LineString([(0, 0)]) + + if numpy: + with self.assertRaisesMessage(ValueError, 'LineString requires at least 2 points, got 1.'): + LineString(numpy.array([(0, 0)])) + + with mock.patch('django.contrib.gis.geos.linestring.numpy', False): + with self.assertRaisesMessage(TypeError, 'Invalid initialization input for LineStrings.'): + LineString('wrong input') def test_multilinestring(self): "Testing MultiLineString objects." @@ -374,12 +382,16 @@ class GEOSTest(SimpleTestCase, TestDataMixin): if numpy: self.assertEqual(lr, LinearRing(numpy.array(lr.tuple))) - with self.assertRaisesMessage(TypeError, 'LinearRing requires at least 4 points, got 3.'): + with self.assertRaisesMessage(ValueError, 'LinearRing requires at least 4 points, got 3.'): LinearRing((0, 0), (1, 1), (0, 0)) - with self.assertRaisesMessage(TypeError, 'LinearRing requires at least 4 points, got 1.'): + with self.assertRaisesMessage(ValueError, 'LinearRing requires at least 4 points, got 1.'): LinearRing([(0, 0)]) + if numpy: + with self.assertRaisesMessage(ValueError, 'LinearRing requires at least 4 points, got 1.'): + LinearRing(numpy.array([(0, 0)])) + def test_polygons_from_bbox(self): "Testing `from_bbox` class method." bbox = (-180, -90, 180, 90)