mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-04 00:04:03 -04:00
[api] Add QgsSipUtils, with method to test if object is owned by Python
QgsSipUtils.isPyOwned will return True if an object is owned by python, or False if ownership is held by another object or c++ class. This gives a way to test in advance if we can safely assign an object to a method which takes ownership (which always results in a crash).
This commit is contained in:
parent
19f246ecb1
commit
72ad735b1e
5
python/PyQt6/core/auto_additions/qgssiputils.py
Normal file
5
python/PyQt6/core/auto_additions/qgssiputils.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# The following has been generated automatically from src/core/qgssiputils.h
|
||||||
|
try:
|
||||||
|
QgsSipUtils.isPyOwned = staticmethod(QgsSipUtils.isPyOwned)
|
||||||
|
except (NameError, AttributeError):
|
||||||
|
pass
|
50
python/PyQt6/core/auto_generated/qgssiputils.sip.in
Normal file
50
python/PyQt6/core/auto_generated/qgssiputils.sip.in
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/qgssiputils.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.py again *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class QgsSipUtils
|
||||||
|
{
|
||||||
|
%Docstring(signature="appended")
|
||||||
|
Contains utilities for working with SIP Python objects.
|
||||||
|
|
||||||
|
.. versionadded:: 3.44
|
||||||
|
%End
|
||||||
|
|
||||||
|
%TypeHeaderCode
|
||||||
|
#include "qgssiputils.h"
|
||||||
|
%End
|
||||||
|
public:
|
||||||
|
|
||||||
|
static bool isPyOwned( SIP_PYOBJECT /GetWrapper/ );
|
||||||
|
%Docstring
|
||||||
|
Returns ``True`` if an object is currently owned by Python.
|
||||||
|
|
||||||
|
If ``False`` is returned, then the object is currently owned by another
|
||||||
|
object (e.g. a c++ class).
|
||||||
|
%End
|
||||||
|
%MethodCode
|
||||||
|
if ( sipIsOwnedByPython( ( sipSimpleWrapper * )a0Wrapper ) )
|
||||||
|
{
|
||||||
|
sipRes = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sipRes = false;
|
||||||
|
}
|
||||||
|
%End
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/qgssiputils.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.py again *
|
||||||
|
************************************************************************/
|
@ -170,6 +170,7 @@
|
|||||||
%Include auto_generated/qgsselectioncontext.sip
|
%Include auto_generated/qgsselectioncontext.sip
|
||||||
%Include auto_generated/qgssimplifymethod.sip
|
%Include auto_generated/qgssimplifymethod.sip
|
||||||
%Include auto_generated/qgssingleitemmodel.sip
|
%Include auto_generated/qgssingleitemmodel.sip
|
||||||
|
%Include auto_generated/qgssiputils.sip
|
||||||
%Include auto_generated/qgssldexportcontext.sip
|
%Include auto_generated/qgssldexportcontext.sip
|
||||||
%Include auto_generated/qgssnappingconfig.sip
|
%Include auto_generated/qgssnappingconfig.sip
|
||||||
%Include auto_generated/qgssnappingutils.sip
|
%Include auto_generated/qgssnappingutils.sip
|
||||||
|
5
python/core/auto_additions/qgssiputils.py
Normal file
5
python/core/auto_additions/qgssiputils.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# The following has been generated automatically from src/core/qgssiputils.h
|
||||||
|
try:
|
||||||
|
QgsSipUtils.isPyOwned = staticmethod(QgsSipUtils.isPyOwned)
|
||||||
|
except (NameError, AttributeError):
|
||||||
|
pass
|
50
python/core/auto_generated/qgssiputils.sip.in
Normal file
50
python/core/auto_generated/qgssiputils.sip.in
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/qgssiputils.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.py again *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class QgsSipUtils
|
||||||
|
{
|
||||||
|
%Docstring(signature="appended")
|
||||||
|
Contains utilities for working with SIP Python objects.
|
||||||
|
|
||||||
|
.. versionadded:: 3.44
|
||||||
|
%End
|
||||||
|
|
||||||
|
%TypeHeaderCode
|
||||||
|
#include "qgssiputils.h"
|
||||||
|
%End
|
||||||
|
public:
|
||||||
|
|
||||||
|
static bool isPyOwned( SIP_PYOBJECT /GetWrapper/ );
|
||||||
|
%Docstring
|
||||||
|
Returns ``True`` if an object is currently owned by Python.
|
||||||
|
|
||||||
|
If ``False`` is returned, then the object is currently owned by another
|
||||||
|
object (e.g. a c++ class).
|
||||||
|
%End
|
||||||
|
%MethodCode
|
||||||
|
if ( sipIsOwnedByPython( ( sipSimpleWrapper * )a0Wrapper ) )
|
||||||
|
{
|
||||||
|
sipRes = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sipRes = false;
|
||||||
|
}
|
||||||
|
%End
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/qgssiputils.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.py again *
|
||||||
|
************************************************************************/
|
@ -170,6 +170,7 @@
|
|||||||
%Include auto_generated/qgsselectioncontext.sip
|
%Include auto_generated/qgsselectioncontext.sip
|
||||||
%Include auto_generated/qgssimplifymethod.sip
|
%Include auto_generated/qgssimplifymethod.sip
|
||||||
%Include auto_generated/qgssingleitemmodel.sip
|
%Include auto_generated/qgssingleitemmodel.sip
|
||||||
|
%Include auto_generated/qgssiputils.sip
|
||||||
%Include auto_generated/qgssldexportcontext.sip
|
%Include auto_generated/qgssldexportcontext.sip
|
||||||
%Include auto_generated/qgssnappingconfig.sip
|
%Include auto_generated/qgssnappingconfig.sip
|
||||||
%Include auto_generated/qgssnappingutils.sip
|
%Include auto_generated/qgssnappingutils.sip
|
||||||
|
@ -1293,6 +1293,7 @@ set(QGIS_CORE_HDRS
|
|||||||
qgsshapegenerator.h
|
qgsshapegenerator.h
|
||||||
qgssimplifymethod.h
|
qgssimplifymethod.h
|
||||||
qgssingleitemmodel.h
|
qgssingleitemmodel.h
|
||||||
|
qgssiputils.h
|
||||||
qgssldexportcontext.h
|
qgssldexportcontext.h
|
||||||
qgssnappingconfig.h
|
qgssnappingconfig.h
|
||||||
qgssnappingutils.h
|
qgssnappingutils.h
|
||||||
|
56
src/core/qgssiputils.h
Normal file
56
src/core/qgssiputils.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgssiputils.h
|
||||||
|
|
||||||
|
-------------------
|
||||||
|
begin : May 2025
|
||||||
|
copyright : (C) 2025 by Nyall Dawson
|
||||||
|
email : nyall dot dawson at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QGSSIPUTILS_H
|
||||||
|
#define QGSSIPUTILS_H
|
||||||
|
#include "qgis_core.h"
|
||||||
|
#include "qgis_sip.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Contains utilities for working with SIP Python objects.
|
||||||
|
*
|
||||||
|
* \ingroup core
|
||||||
|
* \since QGIS 3.44
|
||||||
|
*/
|
||||||
|
class CORE_EXPORT QgsSipUtils
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
#ifdef SIP_RUN
|
||||||
|
/**
|
||||||
|
* Returns TRUE if an object is currently owned by Python.
|
||||||
|
*
|
||||||
|
* If FALSE is returned, then the object is currently owned by another
|
||||||
|
* object (e.g. a c++ class).
|
||||||
|
*/
|
||||||
|
static bool isPyOwned( SIP_PYOBJECT SIP_GETWRAPPER );
|
||||||
|
% MethodCode
|
||||||
|
if ( sipIsOwnedByPython( ( sipSimpleWrapper * )a0Wrapper ) )
|
||||||
|
{
|
||||||
|
sipRes = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sipRes = false;
|
||||||
|
}
|
||||||
|
% End
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //QGSSIPUTILS_H
|
@ -318,6 +318,7 @@ ADD_PYTHON_TEST(PyQgsSingleBandPseudoColorRenderer test_qgssinglebandpseudocolor
|
|||||||
ADD_PYTHON_TEST(PyQgsSingleSymbolRenderer test_qgssinglesymbolrenderer.py)
|
ADD_PYTHON_TEST(PyQgsSingleSymbolRenderer test_qgssinglesymbolrenderer.py)
|
||||||
ADD_PYTHON_TEST(PyQgsRasterSingleColorRenderer test_qgsrastersinglecolorrenderer.py)
|
ADD_PYTHON_TEST(PyQgsRasterSingleColorRenderer test_qgsrastersinglecolorrenderer.py)
|
||||||
ADD_PYTHON_TEST(PyQgsShapefileProvider test_provider_shapefile.py)
|
ADD_PYTHON_TEST(PyQgsShapefileProvider test_provider_shapefile.py)
|
||||||
|
ADD_PYTHON_TEST(PyQgsSipUtils test_qgssiputils.py)
|
||||||
ADD_PYTHON_TEST(PyQgsSphere test_qgssphere.py)
|
ADD_PYTHON_TEST(PyQgsSphere test_qgssphere.py)
|
||||||
ADD_PYTHON_TEST(PyQgsSvgCache test_qgssvgcache.py)
|
ADD_PYTHON_TEST(PyQgsSvgCache test_qgssvgcache.py)
|
||||||
ADD_PYTHON_TEST(PyQgsSymbolLayerRegistry test_qgssymbollayerregistry.py)
|
ADD_PYTHON_TEST(PyQgsSymbolLayerRegistry test_qgssymbollayerregistry.py)
|
||||||
|
43
tests/src/python/test_qgssiputils.py
Normal file
43
tests/src/python/test_qgssiputils.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
"""QGIS Unit tests for QgsSipUtils
|
||||||
|
|
||||||
|
.. note:: This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from qgis.core import (
|
||||||
|
QgsSipUtils,
|
||||||
|
QgsGeometry,
|
||||||
|
QgsSingleSymbolRenderer,
|
||||||
|
QgsPoint,
|
||||||
|
QgsFillSymbol,
|
||||||
|
)
|
||||||
|
import unittest
|
||||||
|
from qgis.testing import QgisTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestQgsSipUtils(QgisTestCase):
|
||||||
|
|
||||||
|
def test_isPyOwned(self):
|
||||||
|
# not a sip object
|
||||||
|
self.assertTrue(QgsSipUtils.isPyOwned(5))
|
||||||
|
|
||||||
|
p = QgsPoint()
|
||||||
|
self.assertTrue(QgsSipUtils.isPyOwned(p))
|
||||||
|
# assign ownership to other object
|
||||||
|
g = QgsGeometry(p)
|
||||||
|
self.assertTrue(QgsSipUtils.isPyOwned(g))
|
||||||
|
self.assertFalse(QgsSipUtils.isPyOwned(p))
|
||||||
|
self.assertFalse(QgsSipUtils.isPyOwned(g.get()))
|
||||||
|
self.assertTrue(QgsSipUtils.isPyOwned(g.get().clone()))
|
||||||
|
|
||||||
|
renderer = QgsSingleSymbolRenderer(QgsFillSymbol.createSimple({}))
|
||||||
|
self.assertFalse(QgsSipUtils.isPyOwned(renderer.symbol()))
|
||||||
|
renderer2 = renderer.clone()
|
||||||
|
# an object created in c++, never seen before by sip/python
|
||||||
|
self.assertFalse(QgsSipUtils.isPyOwned(renderer2.symbol()))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user