From 7931a5c741eaa25ad9f59b3b6f160620846518c0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Oct 2025 15:31:01 +0000 Subject: [PATCH 1/4] Initial plan From 2a92212e7fe83d166161cf23d285000870350671 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Oct 2025 15:42:52 +0000 Subject: [PATCH 2/4] Fix scene context detection to return None by default - Remove commented code that auto-discovered contexts - Update docstring to reflect correct behavior - Fix test indentation (tests were nested incorrectly) - Update test to verify explicit context requirement - Add tests for None default context behavior Co-authored-by: Licini <17893605+Licini@users.noreply.github.com> --- src/compas/scene/context.py | 15 ++++------ tests/compas/scene/test_scene.py | 50 ++++++++++++++++++++++++-------- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/compas/scene/context.py b/src/compas/scene/context.py index c53052a4a233..b9edd1aa3a2d 100644 --- a/src/compas/scene/context.py +++ b/src/compas/scene/context.py @@ -94,15 +94,15 @@ def register(item_type, sceneobject_type, context=None): def detect_current_context(): """Chooses an appropriate context depending on available contexts and open instances. with the following priority: - 1. Viewer - 2. Plotter - 3. Rhino / GH - checked explicitly since SceneObjects for both get registered when code is run from either. - 4. Other + 1. Rhino / GH - checked explicitly since SceneObjects for both get registered when code is run from either. + 2. Blender + 3. None (default) - returns the base scene object type Returns ------- - str - Name of an available context, used as key in :attr:`SceneObject.ITEM_SCENEOBJECT` + str or None + Name of an available context, used as key in :attr:`SceneObject.ITEM_SCENEOBJECT`, + or None if no explicit context is detected. """ @@ -112,9 +112,6 @@ def detect_current_context(): return "Rhino" if compas.is_blender(): return "Blender" - # other_contexts = [v for v in ITEM_SCENEOBJECT.keys()] - # if other_contexts: - # return other_contexts[0] return None diff --git a/tests/compas/scene/test_scene.py b/tests/compas/scene/test_scene.py index fe09c341e078..ccddeccc9015 100644 --- a/tests/compas/scene/test_scene.py +++ b/tests/compas/scene/test_scene.py @@ -66,21 +66,47 @@ def test_get_sceneobject_cls_with_out_of_order_registration(): sceneobject = SceneObject(item, context="fake") assert isinstance(sceneobject, FakeSubSceneObject) - def test_sceneobject_auto_context_discovery(mocker): - register_fake_context() + def test_sceneobject_requires_explicit_context_when_registered(mocker): + """Test that when a context is registered, it must be explicitly specified.""" + register_fake_context() - item = FakeItem() + item = FakeItem() + # Without explicit context, should fail since context is None and FakeItem is not registered for None + with pytest.raises(SceneObjectNotRegisteredError): sceneobject = SceneObject(item) + + # With explicit context, should work + sceneobject = SceneObject(item, context="fake") + assert isinstance(sceneobject, FakeSceneObject) - assert isinstance(sceneobject, FakeSceneObject) - - def test_sceneobject_auto_context_discovery_no_context(mocker): - mocker.patch("compas.scene.context.compas.is_grasshopper", return_value=False) - mocker.patch("compas.scene.context.compas.is_rhino", return_value=False) - - with pytest.raises(SceneObjectNotRegisteredError): - item = FakeSubItem() - _ = SceneObject(item) + def test_sceneobject_auto_context_discovery_no_context(mocker): + mocker.patch("compas.scene.context.compas.is_grasshopper", return_value=False) + mocker.patch("compas.scene.context.compas.is_rhino", return_value=False) + mocker.patch("compas.scene.context.compas.is_blender", return_value=False) + + with pytest.raises(SceneObjectNotRegisteredError): + item = FakeSubItem() + _ = SceneObject(item) + + def test_detect_current_context_returns_none_by_default(mocker): + """Test that detect_current_context returns None when no explicit context is detected.""" + from compas.scene.context import detect_current_context + + mocker.patch("compas.scene.context.compas.is_grasshopper", return_value=False) + mocker.patch("compas.scene.context.compas.is_rhino", return_value=False) + mocker.patch("compas.scene.context.compas.is_blender", return_value=False) + + context = detect_current_context() + assert context is None + + def test_scene_default_context_is_none(mocker): + """Test that Scene has context=None when no explicit context is detected.""" + mocker.patch("compas.scene.context.compas.is_grasshopper", return_value=False) + mocker.patch("compas.scene.context.compas.is_rhino", return_value=False) + mocker.patch("compas.scene.context.compas.is_blender", return_value=False) + + scene = Scene() + assert scene.context is None def test_sceneobject_transform(): scene = Scene() From fcd67856894dde3621ff5830efd490af6e50b57d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Oct 2025 15:43:58 +0000 Subject: [PATCH 3/4] Apply ruff formatting to test file Co-authored-by: Licini <17893605+Licini@users.noreply.github.com> --- tests/compas/scene/test_scene.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/compas/scene/test_scene.py b/tests/compas/scene/test_scene.py index ccddeccc9015..3cb9c73d3095 100644 --- a/tests/compas/scene/test_scene.py +++ b/tests/compas/scene/test_scene.py @@ -74,7 +74,7 @@ def test_sceneobject_requires_explicit_context_when_registered(mocker): # Without explicit context, should fail since context is None and FakeItem is not registered for None with pytest.raises(SceneObjectNotRegisteredError): sceneobject = SceneObject(item) - + # With explicit context, should work sceneobject = SceneObject(item, context="fake") assert isinstance(sceneobject, FakeSceneObject) @@ -91,11 +91,11 @@ def test_sceneobject_auto_context_discovery_no_context(mocker): def test_detect_current_context_returns_none_by_default(mocker): """Test that detect_current_context returns None when no explicit context is detected.""" from compas.scene.context import detect_current_context - + mocker.patch("compas.scene.context.compas.is_grasshopper", return_value=False) mocker.patch("compas.scene.context.compas.is_rhino", return_value=False) mocker.patch("compas.scene.context.compas.is_blender", return_value=False) - + context = detect_current_context() assert context is None @@ -104,7 +104,7 @@ def test_scene_default_context_is_none(mocker): mocker.patch("compas.scene.context.compas.is_grasshopper", return_value=False) mocker.patch("compas.scene.context.compas.is_rhino", return_value=False) mocker.patch("compas.scene.context.compas.is_blender", return_value=False) - + scene = Scene() assert scene.context is None From 5bd89240d68cb27739b2cf8bc7f728aab7a755c2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 15:05:22 +0000 Subject: [PATCH 4/4] Update CHANGELOG.md to document context detection fix Co-authored-by: Licini <17893605+Licini@users.noreply.github.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0ac707d38da..33c09eb80881 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -95,7 +95,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Fixed error in `circle_to_compas` from Rhino. * Fixed Rhino to Rhino brep serialization. * Upated `compas.scene.Group.add()` to pass on group kwargs as default for child items. -* Fixed bug in context detection, which wrongly defaults to `Viewer` instead of `None`. +* Fixed `compas.scene.context.detect_current_context()` to return `None` by default instead of randomly selecting the first registered context, ensuring predictable behavior when creating scene objects without an explicit context. * Fixed bug in calculation of `compas.geometry.Polyhedron.edges` if geometry is computed using numpy. * Fixed bug in `Grpah.from_pointcloud` which uses degree parameter wrongly.