commit 2e04edc4bd5cd1a7db9fad42c0aadb47eeef89c3
parent 59fb2af11208c12eb4b0d3a93427fa564ec1eab5
Author: Anders Damsgaard <anders@adamsgaard.dk>
Date: Fri, 5 Jun 2026 21:39:52 +0300
feat: check addFeatures result; warn and return on failure (A3+B6+T4)
Diffstat:
3 files changed, 50 insertions(+), 3 deletions(-)
diff --git a/profile_interpreter/profile_interpreter.py b/profile_interpreter/profile_interpreter.py
@@ -215,7 +215,14 @@ class ProfileInterpreterPlugin:
for k, v in attrs.items():
feature[k] = v
- layer.dataProvider().addFeatures([feature])
+ ok, _ = layer.dataProvider().addFeatures([feature])
+ if not ok:
+ self.iface.messageBar().pushMessage(
+ MENU,
+ 'Failed to add feature to layer.',
+ level=Qgis.Warning,
+ )
+ return
layer.updateExtents()
layer.triggerRepaint()
diff --git a/test/fakeqgis.py b/test/fakeqgis.py
@@ -217,6 +217,8 @@ class QgsVectorDataProvider:
class _FakeDataProvider:
+ _fail_next = False # set True in a test to simulate addFeatures failure
+
def __init__(self, caps, features_store, fields_ref):
self._caps = caps
self._features = features_store
@@ -226,8 +228,11 @@ class _FakeDataProvider:
return self._caps
def addFeatures(self, features):
+ if _FakeDataProvider._fail_next:
+ _FakeDataProvider._fail_next = False
+ return (False, [])
self._features.extend(features)
- return True
+ return (True, list(features))
def addAttributes(self, attrs):
self._fields_ref.extend(attrs)
diff --git a/test/test_profile_interpreter.py b/test/test_profile_interpreter.py
@@ -76,10 +76,19 @@ class _FakeBar:
pass
+class _TrackingBar:
+ def __init__(self):
+ self.messages = []
+
+ def pushMessage(self, tag, msg, level=None, **kwargs):
+ self.messages.append((tag, msg, level))
+
+
class _FakeIface:
def __init__(self, active_layer=None, canvases=None):
self._active_layer = active_layer
self._window = _FakeMainWindow(canvases or [])
+ self._bar = _FakeBar()
def activeLayer(self):
return self._active_layer
@@ -88,7 +97,7 @@ class _FakeIface:
return self._window
def messageBar(self):
- return _FakeBar()
+ return self._bar
def addPluginToMenu(self, *args):
pass
@@ -399,5 +408,31 @@ class TestFindProfileCanvas(unittest.TestCase):
self.assertIsNone(plugin._find_profile_canvas())
+# ── addFeatures failure ───────────────────────────────────────────────────
+
+class TestOnPickAddFeaturesFailure(unittest.TestCase):
+ def setUp(self):
+ fq.QgsProject._instance = None
+ fq.QgsGeometry._next_interpolate_empty = False
+ fq.QgsCoordinateTransform.reset()
+ fq._FakeDataProvider._fail_next = False
+
+ def test_failure_shows_warning_and_adds_no_features(self):
+ plugin, iface = _make_plugin(active_layer=None)
+ bar = _TrackingBar()
+ iface._bar = bar
+
+ fq._FakeDataProvider._fail_next = True
+ canvas = plugin._canvas
+ plugin._on_pick(_FakeEvent())
+
+ # feature was not committed
+ self.assertEqual(len(plugin._layer._features), 0)
+ # a warning was pushed
+ self.assertTrue(any(level == fq.Qgis.Warning for _, _, level in bar.messages))
+ # canvas was not refreshed
+ self.assertEqual(canvas.refresh_count, 0)
+
+
if __name__ == '__main__':
unittest.main()