Skip to content

Commit f5a6aef

Browse files
committedNov 19, 2018
Raise IndexError in PyQGIS when calling geometryN on a collection
with an invalid geometry index And add len operator to QgsGeometryCollection
1 parent b089b57 commit f5a6aef

File tree

3 files changed

+77
-1
lines changed

3 files changed

+77
-1
lines changed
 

‎python/core/auto_generated/geometry/qgsgeometrycollection.sip.in

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,40 @@ Returns the number of geometries within the collection.
4242
%End
4343

4444

45-
QgsAbstractGeometry *geometryN( int n );
45+
int __len__() const;
46+
%Docstring
47+
Returns the number of geometries within the collection.
48+
%End
49+
%MethodCode
50+
sipRes = sipCpp->numGeometries();
51+
%End
52+
53+
//! Ensures that bool(obj) returns true (otherwise __len__() would be used)
54+
int __bool__() const;
55+
%MethodCode
56+
sipRes = true;
57+
%End
58+
59+
60+
61+
SIP_PYOBJECT geometryN( int n ) const;
4662
%Docstring
4763
Returns a geometry from within the collection.
4864

4965
:param n: index of geometry to return
5066
%End
67+
%MethodCode
68+
if ( a0 < 0 || a0 >= sipCpp->numGeometries() )
69+
{
70+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
71+
sipIsErr = 1;
72+
}
73+
else
74+
{
75+
return sipConvertFromType( sipCpp->geometryN( a0 ), sipType_QgsAbstractGeometry, NULL );
76+
}
77+
%End
78+
5179

5280
virtual bool isEmpty() const;
5381

‎src/core/geometry/qgsgeometrycollection.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,24 @@ class CORE_EXPORT QgsGeometryCollection: public QgsAbstractGeometry
5353
return mGeometries.size();
5454
}
5555

56+
#ifdef SIP_RUN
57+
58+
/**
59+
* Returns the number of geometries within the collection.
60+
*/
61+
int __len__() const;
62+
% MethodCode
63+
sipRes = sipCpp->numGeometries();
64+
% End
65+
66+
//! Ensures that bool(obj) returns true (otherwise __len__() would be used)
67+
int __bool__() const;
68+
% MethodCode
69+
sipRes = true;
70+
% End
71+
#endif
72+
73+
5674
/**
5775
* Returns a const reference to a geometry from within the collection.
5876
* \param n index of geometry to return
@@ -67,7 +85,23 @@ class CORE_EXPORT QgsGeometryCollection: public QgsAbstractGeometry
6785
* Returns a geometry from within the collection.
6886
* \param n index of geometry to return
6987
*/
88+
#ifndef SIP_RUN
7089
QgsAbstractGeometry *geometryN( int n );
90+
#else
91+
SIP_PYOBJECT geometryN( int n ) const;
92+
% MethodCode
93+
if ( a0 < 0 || a0 >= sipCpp->numGeometries() )
94+
{
95+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
96+
sipIsErr = 1;
97+
}
98+
else
99+
{
100+
return sipConvertFromType( sipCpp->geometryN( a0 ), sipType_QgsAbstractGeometry, NULL );
101+
}
102+
% End
103+
#endif
104+
71105

72106
//methods inherited from QgsAbstractGeometry
73107
bool isEmpty() const override;

‎tests/src/python/test_qgsgeometry.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,20 @@ def testReferenceGeometry(self):
242242
result = geom.constGet().perimeter()
243243
self.assertAlmostEqual(result, exp, 5, "Perimeter {}: mismatch Expected:\n{}\nGot:\n{}\n".format(i + 1, exp, result))
244244

245+
def testCollection(self):
246+
g = QgsGeometry.fromWkt('MultiLineString()')
247+
self.assertEqual(len(g.get()), 0)
248+
self.assertTrue(g.get())
249+
g = QgsGeometry.fromWkt('MultiLineString((0 0, 1 1),(13 2, 14 1))')
250+
self.assertEqual(len(g.get()), 2)
251+
self.assertTrue(g.get())
252+
self.assertEqual(g.get().geometryN(0).asWkt(), 'LineString (0 0, 1 1)')
253+
self.assertEqual(g.get().geometryN(1).asWkt(), 'LineString (13 2, 14 1)')
254+
with self.assertRaises(IndexError):
255+
g.get().geometryN(-1)
256+
with self.assertRaises(IndexError):
257+
g.get().geometryN(2)
258+
245259
def testIntersection(self):
246260
myLine = QgsGeometry.fromPolylineXY([
247261
QgsPointXY(0, 0),

0 commit comments

Comments
 (0)
Please sign in to comment.