Skip to content
Permalink
Browse files
Raise IndexErrors instead of crashing when an invalid index is
passed to QgsAttributeTableConfig methods from Python
  • Loading branch information
nyalldawson committed Aug 17, 2021
1 parent 49c150c commit d4b68ae7fc68296a3ac63249c7cb0c64f4f1269a
@@ -64,6 +64,20 @@ The list order defines the order of appearance.
bool isEmpty() const;
%Docstring
Returns ``True`` if the configuration is empty, ie it contains no columns.

.. seealso:: :py:func:`size`
%End

int size() const;
%Docstring
Returns the number of columns in the configuration.

.. versionadded:: 3.22
%End

int __len__() const;
%MethodCode
sipRes = sipCpp->size();
%End

int mapVisibleColumnToIndex( int visibleColumn ) const;
@@ -129,14 +143,31 @@ Gets the expression used for sorting.
Set the sort expression used for sorting.
%End


int columnWidth( int column ) const;
%Docstring
Returns the width of a column, or -1 if column should use default width.

:param column: column index

:raises IndexError: if the column is not found

.. seealso:: :py:func:`setColumnWidth`
%End
%MethodCode
{
if ( a0 < 0 || a0 >= sipCpp->size() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
return PyLong_FromLong( sipCpp->columnWidth( a0 ) );
}
}
%End


void setColumnWidth( int column, int width );
%Docstring
@@ -145,17 +176,47 @@ Sets the width of a column.
:param column: column index
:param width: column width in pixels, or -1 if column should use default width

:raises IndexError: if the column is not found

.. seealso:: :py:func:`columnWidth`
%End
%MethodCode
if ( a0 < 0 || a0 >= sipCpp->size() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
sipCpp->setColumnWidth( a0, a1 );
}
%End


bool columnHidden( int column ) const;
%Docstring
Returns ``True`` if the specified column is hidden.

:param column: column index

:raises IndexError: if the column is not found

.. seealso:: :py:func:`setColumnHidden`
%End
%MethodCode
{
if ( a0 < 0 || a0 >= sipCpp->size() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
return PyBool_FromLong( sipCpp->columnHidden( a0 ) );
}
}
%End


void setColumnHidden( int column, bool hidden );
%Docstring
@@ -164,7 +225,20 @@ Sets whether the specified column should be hidden.
:param column: column index
:param hidden: set to ``True`` to hide column

:raises IndexError: if the column is not found

.. seealso:: :py:func:`columnHidden`
%End
%MethodCode
if ( a0 < 0 || a0 >= sipCpp->size() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
sipCpp->setColumnHidden( a0, a1 );
}
%End

Qt::SortOrder sortOrder() const;
@@ -27,6 +27,11 @@ bool QgsAttributeTableConfig::isEmpty() const
return mColumns.isEmpty();
}

int QgsAttributeTableConfig::size() const
{
return mColumns.size();
}

int QgsAttributeTableConfig::mapVisibleColumnToIndex( int visibleColumn ) const
{
for ( int i = 0; i < mColumns.size(); ++i )
@@ -84,9 +84,25 @@ class CORE_EXPORT QgsAttributeTableConfig

/**
* Returns TRUE if the configuration is empty, ie it contains no columns.
*
* \see size()
*/
bool isEmpty() const;

/**
* Returns the number of columns in the configuration.
*
* \since QGIS 3.22
*/
int size() const;

#ifdef SIP_RUN
int __len__() const;
% MethodCode
sipRes = sipCpp->size();
% End
#endif

/**
* Maps a visible column index to its original column index.
* \param visibleColumn index of visible column
@@ -148,27 +164,103 @@ class CORE_EXPORT QgsAttributeTableConfig
*/
void setSortExpression( const QString &sortExpression );

#ifndef SIP_RUN

/**
* Returns the width of a column, or -1 if column should use default width.
* \param column column index
* \see setColumnWidth()
*/
int columnWidth( int column ) const;
#else

/**
* Returns the width of a column, or -1 if column should use default width.
* \param column column index
* \throws IndexError if the column is not found
* \see setColumnWidth()
*/
int columnWidth( int column ) const;
% MethodCode
{
if ( a0 < 0 || a0 >= sipCpp->size() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
return PyLong_FromLong( sipCpp->columnWidth( a0 ) );
}
}
% End
#endif

#ifndef SIP_RUN

/**
* Sets the width of a column.
* \param column column index
* \param width column width in pixels, or -1 if column should use default width
* \see columnWidth()
*/
void setColumnWidth( int column, int width );
#else

/**
* Sets the width of a column.
* \param column column index
* \param width column width in pixels, or -1 if column should use default width
* \throws IndexError if the column is not found
* \see columnWidth()
*/
void setColumnWidth( int column, int width );
% MethodCode
if ( a0 < 0 || a0 >= sipCpp->size() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
sipCpp->setColumnWidth( a0, a1 );
}
% End
#endif

#ifndef SIP_RUN

/**
* Returns TRUE if the specified column is hidden.
* \param column column index
* \see setColumnHidden()
*/
bool columnHidden( int column ) const;
#else

/**
* Returns TRUE if the specified column is hidden.
* \param column column index
* \throws IndexError if the column is not found
* \see setColumnHidden()
*/
bool columnHidden( int column ) const;
% MethodCode
{
if ( a0 < 0 || a0 >= sipCpp->size() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
return PyBool_FromLong( sipCpp->columnHidden( a0 ) );
}
}
% End
#endif

#ifndef SIP_RUN

/**
* Sets whether the specified column should be hidden.
@@ -177,6 +269,28 @@ class CORE_EXPORT QgsAttributeTableConfig
* \see columnHidden()
*/
void setColumnHidden( int column, bool hidden );
#else

/**
* Sets whether the specified column should be hidden.
* \param column column index
* \param hidden set to TRUE to hide column
* \throws IndexError if the column is not found
* \see columnHidden()
*/
void setColumnHidden( int column, bool hidden );
% MethodCode
if ( a0 < 0 || a0 >= sipCpp->size() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
sipCpp->setColumnHidden( a0, a1 );
}
% End
#endif

/**
* Gets the sort order
@@ -53,6 +53,21 @@ def testIsEmpty(self):
config.setColumns([c])
self.assertFalse(config.isEmpty())

def testSize(self):
"""
Test QgsAttributeTableConfig.size and __len__
"""
config = QgsAttributeTableConfig()
self.assertEqual(config.size(), 0)
self.assertEqual(len(config), 0)

c1 = QgsAttributeTableConfig.ColumnConfig()
c2 = QgsAttributeTableConfig.ColumnConfig()
config.setColumns([c1, c2])

self.assertEqual(config.size(), 2)
self.assertEqual(len(config), 2)

def testSetColumns(self):
""" test setting columns """
config = QgsAttributeTableConfig()
@@ -90,6 +105,11 @@ def testColumnHidden(self):
self.assertFalse(config.columnHidden(0))
self.assertFalse(config.columnHidden(1))

with self.assertRaises(IndexError):
config.columnHidden(-1)
with self.assertRaises(IndexError):
config.columnHidden(2)

config.setColumnHidden(1, True)
self.assertFalse(config.columnHidden(0))
self.assertTrue(config.columnHidden(1))
@@ -102,11 +122,58 @@ def testColumnHidden(self):
self.assertTrue(config.columns()[0].hidden)
self.assertTrue(config.columns()[1].hidden)

with self.assertRaises(IndexError):
config.setColumnHidden(-1, True)
with self.assertRaises(IndexError):
config.setColumnHidden(2, True)

c2.hidden = True
config.setColumns([c1, c2])
self.assertFalse(config.columnHidden(0))
self.assertTrue(config.columnHidden(1))

def testColumnWidth(self):
""" test setting column widths """

config = QgsAttributeTableConfig()
c1 = QgsAttributeTableConfig.ColumnConfig()
c1.name = 'test'
c1.width = -1
c2 = QgsAttributeTableConfig.ColumnConfig()
c2.name = 'test2'
c2.width = 27
config.setColumns([c1, c2])

self.assertEqual(config.columnWidth(0), -1)
self.assertEqual(config.columnWidth(1), 27)

with self.assertRaises(IndexError):
config.columnWidth(-1)
with self.assertRaises(IndexError):
config.columnWidth(2)

config.setColumnWidth(1, -1)
self.assertEqual(config.columnWidth(0), -1)
self.assertEqual(config.columnWidth(1), -1)
self.assertEqual(config.columns()[0].width, -1)
self.assertEqual(config.columns()[1].width, -1)

config.setColumnWidth(0, 34)
self.assertEqual(config.columnWidth(0), 34)
self.assertEqual(config.columnWidth(1), -1)
self.assertEqual(config.columns()[0].width, 34)
self.assertEqual(config.columns()[1].width, -1)

with self.assertRaises(IndexError):
config.setColumnWidth(-1, 11)
with self.assertRaises(IndexError):
config.setColumnWidth(2, 11)

c2.width = 12
config.setColumns([c1, c2])
self.assertEqual(config.columnWidth(0), -1)
self.assertEqual(config.columnWidth(1), 12)

def testSameColumns(self):
""" test hasSameColumns() check """

0 comments on commit d4b68ae

Please sign in to comment.