This is an automated email from the ASF dual-hosted git repository. spmallette pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit a75784e1635a881cbcb1fcb319c50f4184f4de88 Author: Stephen Mallette <[email protected]> AuthorDate: Mon Jul 20 08:16:28 2026 -0400 Fixed toString on Tree in Gremlin Console CTR --- .../apache/tinkerpop/gremlin/groovy/loaders/SugarLoader.groovy | 7 +++++++ .../org/apache/tinkerpop/gremlin/groovy/TreeSubscriptTest.groovy | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/SugarLoader.groovy b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/SugarLoader.groovy index 5f33f27723..7eb732d728 100644 --- a/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/SugarLoader.groovy +++ b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/SugarLoader.groovy @@ -99,6 +99,13 @@ class SugarLoader { public static final Object getAt(final Tree tree, final Object key) { return tree.childAt(key); } + + // Mixing this category into Tree.metaClass shadows Tree's own toString() with the + // category delegate's Object.toString(), which renders as "...$TreeCategory@<hash>". + // Reflectively invoke the real Tree.toString() so the console shows the nested nodes. + public String toString() { + return Tree.class.getMethod("toString").invoke(this.metaClass.owner); + } } public static class ElementCategory { diff --git a/gremlin-groovy/src/test/groovy/org/apache/tinkerpop/gremlin/groovy/TreeSubscriptTest.groovy b/gremlin-groovy/src/test/groovy/org/apache/tinkerpop/gremlin/groovy/TreeSubscriptTest.groovy index b2d068e2c4..ac2a489b73 100644 --- a/gremlin-groovy/src/test/groovy/org/apache/tinkerpop/gremlin/groovy/TreeSubscriptTest.groovy +++ b/gremlin-groovy/src/test/groovy/org/apache/tinkerpop/gremlin/groovy/TreeSubscriptTest.groovy @@ -53,6 +53,15 @@ class TreeSubscriptTest { assertTrue(tree['marko']['josh'].rootNodes().contains('lop')) } + @Test + public void shouldRenderNestedToStringViaSugar() { + def g = TinkerFactory.createModern().traversal() + Tree tree = g.V(1).out().out().tree().by('name').next() + + // The mixin must not shadow Tree's toString() with the category delegate's identity string. + assertEquals('{marko={josh={ripple={}, lop={}}}}', tree.toString()) + } + @Test public void shouldThrowOnMissingSubscriptKey() { def g = TinkerFactory.createModern().traversal()
