This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a commit to branch TINKERPOP-3119
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 8f4182e8125993f80e8bcf83659ce78dfbe0140c
Author: Stephen Mallette <[email protected]>
AuthorDate: Thu Feb 19 10:14:39 2026 -0500

    TINKERPOP-3119 Added better pythonic access for properties
    
    Much of this became possible with properties on elements and then the 
addition of subgraph() support.
---
 CHANGELOG.asciidoc                                  |  1 +
 .../main/python/gremlin_python/structure/graph.py   |  9 +++++++++
 .../main/python/tests/unit/structure/test_graph.py  | 21 +++++++++++++++++++++
 3 files changed, 31 insertions(+)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 972d496e0a..2f084c9ba8 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -23,6 +23,7 @@ 
image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 [[release-4-0-0]]
 === TinkerPop 4.0.0 (NOT OFFICIALLY RELEASED YET)
 
+* Added `__contains__` and `keys()` to `Element` in `gremlin-python`.
 * Added `subgraph()` support for `gremlin-python` so that results are stored 
in a detached `Graph` object.
 * Modified grammar to make `discard()` usage more consistent as a filter step 
where it can now be used to chain additional traversal steps and be used 
anonymously.
 * Removed `Meta` field from `ResponseResult` struct in `gremlin-go`
diff --git a/gremlin-python/src/main/python/gremlin_python/structure/graph.py 
b/gremlin-python/src/main/python/gremlin_python/structure/graph.py
index d3965b2916..87b633703c 100644
--- a/gremlin-python/src/main/python/gremlin_python/structure/graph.py
+++ b/gremlin-python/src/main/python/gremlin_python/structure/graph.py
@@ -41,6 +41,15 @@ class Element(object):
                 return p.value
         raise KeyError(key)
 
+    def __contains__(self, key):
+        for p in self.properties:
+            if p.key == key:
+                return True
+        return False
+
+    def keys(self):
+        return set(p.key for p in self.properties)
+
     def values(self, *property_keys):
         if len(property_keys) == 0:
             return [p.value for p in self.properties]
diff --git a/gremlin-python/src/main/python/tests/unit/structure/test_graph.py 
b/gremlin-python/src/main/python/tests/unit/structure/test_graph.py
index c9d41f61d9..7882a28430 100644
--- a/gremlin-python/src/main/python/tests/unit/structure/test_graph.py
+++ b/gremlin-python/src/main/python/tests/unit/structure/test_graph.py
@@ -161,3 +161,24 @@ class TestGraph(object):
         assert vp["acl"] == "public"
         assert vp.values("acl") == ["public"]
         assert vp.values() == ["public"]
+
+    def test_element_contains_and_keys(self):
+        v = Vertex(1, "person", [VertexProperty(10, "name", "marko", 
Vertex(1)),
+                                 VertexProperty(11, "age", 29, Vertex(1))])
+        assert "name" in v
+        assert "age" in v
+        assert "nonexistent" not in v
+        assert v.keys() == {"name", "age"}
+
+        e = Edge(2, Vertex(1), "knows", Vertex(3), [Property("weight", 0.5, 
None)])
+        assert "weight" in e
+        assert "missing" not in e
+        assert e.keys() == {"weight"}
+
+        empty_v = Vertex(99)
+        assert "anything" not in empty_v
+        assert empty_v.keys() == set()
+
+        # supports the pattern: vertex[key] if key in vertex else None
+        assert v["name"] if "name" in v else None == "marko"
+        assert v["missing"] if "missing" in v else None is None

Reply via email to