Skip to content

Commit

Permalink
Optimise QgsFeature __getitem__
Browse files Browse the repository at this point in the history
Avoid calling expensive sipConvertFromNewType method when feature
attribute is a trivial type
Also avoid a copy of the feature attributes which we don't require
  • Loading branch information
nyalldawson committed Jun 12, 2024
1 parent 40c7534 commit 6240477
Show file tree
Hide file tree
Showing 3 changed files with 249 additions and 18 deletions.
89 changes: 83 additions & 6 deletions python/PyQt6/core/auto_generated/qgsfeature.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,54 @@ geometry and a list of field/values attributes.

SIP_PYOBJECT __getitem__( int key ) /HoldGIL/;
%MethodCode
QgsAttributes attrs = sipCpp->attributes();
if ( a0 < 0 || a0 >= attrs.count() )
if ( a0 < 0 || a0 >= sipCpp->attributeCount() )
{
PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
QVariant *v = new QVariant( attrs.at( a0 ) );
sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
const QVariant v = sipCpp->attribute( a0 );
switch ( v.userType() )
{
case QMetaType::Type::Int:
sipRes = PyLong_FromLong( v.toInt() );
break;

case QMetaType::Type::UInt:
sipRes = PyLong_FromUnsignedLong( v.toUInt() );
break;

case QMetaType::Type::Long:
case QMetaType::Type::LongLong:
sipRes = PyLong_FromLongLong( v.toLongLong() );
break;

case QMetaType::Type::ULong:
case QMetaType::Type::ULongLong:
sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
break;

case QMetaType::Type::Bool:
sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
break;

case QMetaType::Type::Float:
case QMetaType::Type::Double:
sipRes = PyFloat_FromDouble( v.toDouble() );
break;

case QMetaType::Type::QString:
sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
break;

default:
{
QVariant *newV = new QVariant( v );
sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
break;
}
}
}
%End

Expand All @@ -66,8 +104,47 @@ geometry and a list of field/values attributes.
}
else
{
QVariant *v = new QVariant( sipCpp->attribute( fieldIdx ) );
sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
const QVariant v = sipCpp->attribute( fieldIdx );
switch ( v.userType() )
{
case QMetaType::Type::Int:
sipRes = PyLong_FromLong( v.toInt() );
break;

case QMetaType::Type::UInt:
sipRes = PyLong_FromUnsignedLong( v.toUInt() );
break;

case QMetaType::Type::Long:
case QMetaType::Type::LongLong:
sipRes = PyLong_FromLongLong( v.toLongLong() );
break;

case QMetaType::Type::ULong:
case QMetaType::Type::ULongLong:
sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
break;

case QMetaType::Type::Bool:
sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
break;

case QMetaType::Type::Float:
case QMetaType::Type::Double:
sipRes = PyFloat_FromDouble( v.toDouble() );
break;

case QMetaType::Type::QString:
sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
break;

default:
{
QVariant *newV = new QVariant( v );
sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
break;
}
}
}
%End

Expand Down
89 changes: 83 additions & 6 deletions python/core/auto_generated/qgsfeature.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,54 @@ geometry and a list of field/values attributes.

SIP_PYOBJECT __getitem__( int key ) /HoldGIL/;
%MethodCode
QgsAttributes attrs = sipCpp->attributes();
if ( a0 < 0 || a0 >= attrs.count() )
if ( a0 < 0 || a0 >= sipCpp->attributeCount() )
{
PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
QVariant *v = new QVariant( attrs.at( a0 ) );
sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
const QVariant v = sipCpp->attribute( a0 );
switch ( v.userType() )
{
case QMetaType::Type::Int:
sipRes = PyLong_FromLong( v.toInt() );
break;

case QMetaType::Type::UInt:
sipRes = PyLong_FromUnsignedLong( v.toUInt() );
break;

case QMetaType::Type::Long:
case QMetaType::Type::LongLong:
sipRes = PyLong_FromLongLong( v.toLongLong() );
break;

case QMetaType::Type::ULong:
case QMetaType::Type::ULongLong:
sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
break;

case QMetaType::Type::Bool:
sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
break;

case QMetaType::Type::Float:
case QMetaType::Type::Double:
sipRes = PyFloat_FromDouble( v.toDouble() );
break;

case QMetaType::Type::QString:
sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
break;

default:
{
QVariant *newV = new QVariant( v );
sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
break;
}
}
}
%End

Expand All @@ -66,8 +104,47 @@ geometry and a list of field/values attributes.
}
else
{
QVariant *v = new QVariant( sipCpp->attribute( fieldIdx ) );
sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
const QVariant v = sipCpp->attribute( fieldIdx );
switch ( v.userType() )
{
case QMetaType::Type::Int:
sipRes = PyLong_FromLong( v.toInt() );
break;

case QMetaType::Type::UInt:
sipRes = PyLong_FromUnsignedLong( v.toUInt() );
break;

case QMetaType::Type::Long:
case QMetaType::Type::LongLong:
sipRes = PyLong_FromLongLong( v.toLongLong() );
break;

case QMetaType::Type::ULong:
case QMetaType::Type::ULongLong:
sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
break;

case QMetaType::Type::Bool:
sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
break;

case QMetaType::Type::Float:
case QMetaType::Type::Double:
sipRes = PyFloat_FromDouble( v.toDouble() );
break;

case QMetaType::Type::QString:
sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
break;

default:
{
QVariant *newV = new QVariant( v );
sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
break;
}
}
}
%End

Expand Down
89 changes: 83 additions & 6 deletions src/core/qgsfeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,54 @@ class CORE_EXPORT QgsFeature

SIP_PYOBJECT __getitem__( int key ) SIP_HOLDGIL;
% MethodCode
QgsAttributes attrs = sipCpp->attributes();
if ( a0 < 0 || a0 >= attrs.count() )
if ( a0 < 0 || a0 >= sipCpp->attributeCount() )
{
PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
QVariant *v = new QVariant( attrs.at( a0 ) );
sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
const QVariant v = sipCpp->attribute( a0 );
switch ( v.userType() )
{
case QMetaType::Type::Int:
sipRes = PyLong_FromLong( v.toInt() );
break;

case QMetaType::Type::UInt:
sipRes = PyLong_FromUnsignedLong( v.toUInt() );
break;

case QMetaType::Type::Long:
case QMetaType::Type::LongLong:
sipRes = PyLong_FromLongLong( v.toLongLong() );
break;

case QMetaType::Type::ULong:
case QMetaType::Type::ULongLong:
sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
break;

case QMetaType::Type::Bool:
sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
break;

case QMetaType::Type::Float:
case QMetaType::Type::Double:
sipRes = PyFloat_FromDouble( v.toDouble() );
break;

case QMetaType::Type::QString:
sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
break;

default:
{
QVariant *newV = new QVariant( v );
sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
break;
}
}
}
% End

Expand All @@ -101,8 +139,47 @@ class CORE_EXPORT QgsFeature
}
else
{
QVariant *v = new QVariant( sipCpp->attribute( fieldIdx ) );
sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
const QVariant v = sipCpp->attribute( fieldIdx );
switch ( v.userType() )
{
case QMetaType::Type::Int:
sipRes = PyLong_FromLong( v.toInt() );
break;

case QMetaType::Type::UInt:
sipRes = PyLong_FromUnsignedLong( v.toUInt() );
break;

case QMetaType::Type::Long:
case QMetaType::Type::LongLong:
sipRes = PyLong_FromLongLong( v.toLongLong() );
break;

case QMetaType::Type::ULong:
case QMetaType::Type::ULongLong:
sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
break;

case QMetaType::Type::Bool:
sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
break;

case QMetaType::Type::Float:
case QMetaType::Type::Double:
sipRes = PyFloat_FromDouble( v.toDouble() );
break;

case QMetaType::Type::QString:
sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
break;

default:
{
QVariant *newV = new QVariant( v );
sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
break;
}
}
}
% End

Expand Down

0 comments on commit 6240477

Please sign in to comment.