Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
15 changes: 6 additions & 9 deletions src/compas/scene/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.

"""

Expand All @@ -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

Expand Down
46 changes: 36 additions & 10 deletions tests/compas/scene/test_scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

assert isinstance(sceneobject, FakeSceneObject)
# With explicit context, should work
sceneobject = SceneObject(item, context="fake")
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)
mocker.patch("compas.scene.context.compas.is_blender", 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)
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

with pytest.raises(SceneObjectNotRegisteredError):
item = FakeSubItem()
_ = SceneObject(item)
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()
Expand Down
Loading