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


The following commit(s) were added to refs/heads/master by this push:
     new 26881ebdc5 Added support for property assertion
26881ebdc5 is described below

commit 26881ebdc562d0c9872b6a094e32750d9e9c6ae0
Author: Stephen Mallette <[email protected]>
AuthorDate: Wed Feb 18 14:26:18 2026 -0500

    Added support for property assertion
    
    Property assertion isn't perfect but it's a best effort that at least lets 
the test suite exercise this data type a bit. Removed handlers for syntax no 
longer supported and fixed up some tests that were impacted. CTR
---
 docs/src/dev/developer/for-committers.asciidoc     |  9 ++-
 gremlin-go/driver/cucumber/cucumberSteps_test.go   |  9 +++
 gremlin-go/driver/cucumber/gremlin.go              | 11 +++-
 .../gremlin-javascript/test/cucumber/gremlin.js    | 11 +++-
 .../src/main/python/tests/feature/feature_steps.py |  9 +++
 .../src/main/python/tests/feature/gremlin.py       | 11 +++-
 .../tinkerpop/gremlin/features/StepDefinition.java | 25 +++----
 .../gremlin/test/features/map/Edge.feature         | 24 ++-----
 .../gremlin/test/features/map/Properties.feature   | 77 ++++++++++++++++++----
 .../test/features/semantics/Orderability.feature   | 64 ++++++++++++++++++
 10 files changed, 192 insertions(+), 58 deletions(-)

diff --git a/docs/src/dev/developer/for-committers.asciidoc 
b/docs/src/dev/developer/for-committers.asciidoc
index 822909a0c2..09840a706b 100644
--- a/docs/src/dev/developer/for-committers.asciidoc
+++ b/docs/src/dev/developer/for-committers.asciidoc
@@ -412,8 +412,10 @@ included to further qualify the type of numeric. The 
following options are avail
 * Path - *p[_xxx_,_yyy_,_zzz_,...]* - A comma separated collection of values 
that make up the `Path` should be added to
 between the square brackets. These values respect the type system thus 
allowing for creation of `Path` of vertices,
 edges, maps, and any other available type.
+* Property - *prop[_key_,_value_]* - The key is simply a string, and the value 
is expected to be a typed value using the
+syntax presented here.
 * Set - *s[_xxx_,_yyy_,_zzz_,...]* - A comma separated collection of values 
that make up the set should be added to
-between the square brackets. These values respect the type system thus 
allowing for creation of sets of vertices,
+between the square brackets. These values respect the type system thus 
allowing to create sets of vertices,
 edges, maps, and any other available type.
 * String - Any value not using the system notation will be interpreted as
 a string by default.
@@ -423,6 +425,11 @@ such as null and spaces.
 * Vertex - *v[_xxx_]* - The "xxx" should be replaced with the "name" property 
of a vertex in the graph. This syntax may
 include the `.id` suffix which would indicate getting the vertex identifier or 
the `.sid` suffix which gets a string
 representation of the edge identifier.
+* VertexProperty - *vp[_xxx_]* - The "xxx" should be replaced with a 
representation of a vertex property in the form of
+the `vertex_name-key->value`. Note that the key is just a string and the value 
is a typed value using the syntax
+presented here.
+
+vp[marko-name->marko]
 
 In addition, parameter names should adhere to a common form as they hold some 
meaning to certain language variant
 implementations:
diff --git a/gremlin-go/driver/cucumber/cucumberSteps_test.go 
b/gremlin-go/driver/cucumber/cucumberSteps_test.go
index c5b0e2d9ee..6ac7aa5487 100644
--- a/gremlin-go/driver/cucumber/cucumberSteps_test.go
+++ b/gremlin-go/driver/cucumber/cucumberSteps_test.go
@@ -56,6 +56,7 @@ func init() {
                regexp.MustCompile(`^d\[(.*)]\.[n]$`):     toBigInt,
                regexp.MustCompile(`^d\[(.*)]\.[i]$`):     toInt32,
                regexp.MustCompile(`^vp\[(.+)]$`):         toVertexProperty,
+               regexp.MustCompile(`^prop\[(.+)]$`):       toProperty,
                regexp.MustCompile(`^v\[(.+)]$`):          toVertex,
                regexp.MustCompile(`^v\[(.+)]\.id$`):      toVertexId,
                regexp.MustCompile(`^e\[(.+)]$`):          toEdge,
@@ -174,6 +175,14 @@ func toInt32(stringVal, graphName string) interface{} {
        return int32(val)
 }
 
+// Parse property as key/value pair.
+func toProperty(stringVal, graphName string) interface{} {
+       commaIdx := strings.Index(stringVal, ",")
+       key := stringVal[:commaIdx]
+       value := parseValue(stringVal[commaIdx+1:], graphName)
+       return &gremlingo.Property{Key: key, Value: value}
+}
+
 // Parse vertex property.
 func toVertexProperty(name, graphName string) interface{} {
        if vp, ok := tg.getDataGraphFromMap(graphName).vertexProperties[name]; 
ok {
diff --git a/gremlin-go/driver/cucumber/gremlin.go 
b/gremlin-go/driver/cucumber/gremlin.go
index af2643c77b..cbc8080890 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -1114,9 +1114,8 @@ var translationMap = map[string][]func(g 
*gremlingo.GraphTraversalSource, p map[
     "g_E": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.E()}}, 
     "g_EX11X": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["eid11"])}}, 
     "g_EX11AsStringX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["eid11"])}}, 
-    "g_EXe11X": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["e11"])}}, 
-    "g_EXe7_e11X": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["e7"], 
p["e11"])}}, 
-    "g_EXlistXe7_e11XX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["xx1"])}}, 
+    "g_EXeid7_eid11X": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["eid7"], 
p["eid11"])}}, 
+    "g_EXlistXeid7_eid11XX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["xx1"])}}, 
     "g_EXnullX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.E(nil)}}, 
     "g_EXlistXnullXX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["xx1"])}}, 
     "g_EX11_nullX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["eid11"], 
nil)}}, 
@@ -1525,6 +1524,10 @@ var translationMap = map[string][]func(g 
*gremlingo.GraphTraversalSource, p map[
     "g_V_hasXageX_propertiesXage_nameX_value": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.V().Has("age").Properties("age", 
"name").Value()}}, 
     "g_V_propertiesXname_age_nullX_value": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.V().Properties("name", "age", 
nil).Value()}}, 
     "g_V_valuesXname_age_nullX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("name", 
"age", nil)}}, 
+    "g_E_propertiesXweightX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.E().Properties("weight")}}, 
+    "g_E_properties": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.AddV("person").Property("name", 
"alice").As("a").AddV("person").Property("name", 
"bob").As("b").AddE("knows").From("a").To("b").Property("weight", 
0.5).Property("since", int32(2020))}, func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.E().Properties()}}, 
+    "g_E_propertiesXsinceX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.AddV("person").Property("name", 
"alice").As("a").AddV("person").Property("name", 
"bob").As("b").AddE("knows").From("a").To("b").Property("weight", 
0.5).Property("since", int32(2020))}, func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.E().Properties("since")}}, 
+    "g_E_properties_multi_edges": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.AddV("person").Property("name", 
"alice").As("a").AddV("person").Property("name", 
"bob").As("b").AddE("knows").From("a").To("b").Property("weight", 
0.5).Property("since", 
int32(2020)).AddE("likes").From("a").To("b").Property("weight", 
1.0).Property("tag", "friend")}, func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraver [...]
     "g_injectX__feature___test__nullX_rTrim": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Inject("feature  ", "one test ", nil, "", " 
", " abc", "abc ", " abc ", "  ").RTrim()}}, 
     "g_injectX__feature___test__nullX_rTrimXlocalX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Inject([]interface{}{"  feature  ", " one 
test ", nil, "", " ", " abc", "abc ", " abc ", "  
"}).RTrim(gremlingo.Scope.Local)}}, 
     "g_injectX__feature__X_rTrim": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject("  feature  
").RTrim()}}, 
@@ -1895,6 +1898,8 @@ var translationMap = map[string][]func(g 
*gremlingo.GraphTraversalSource, p map[
     "g_V_properties_order_id": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V().Properties().Order().Id()}}, 
     "g_E_properties_order_value": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.AddV("person").Property("name", 
"alice").As("a").AddE("self").From("a").To("a").Property("weight", 
0.5).Property("a", int32(10)).AddE("self").From("a").To("a").Property("weight", 
1.0).Property("a", int32(11)).AddE("self").From("a").To("a").Property("weight", 
0.4).Property("a", int32(12)).AddE("self").From("a").To("a").Property("weight", 
1.0).Property("a [...]
     "g_E_properties_order_byXdescX_value": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.AddV("person").Property("name", 
"alice").As("a").AddE("self").From("a").To("a").Property("weight", 
0.5).Property("a", int32(10)).AddE("self").From("a").To("a").Property("weight", 
1.0).Property("a", int32(11)).AddE("self").From("a").To("a").Property("weight", 
0.4).Property("a", int32(12)).AddE("self").From("a").To("a").Property("weight", 
1.0).Pr [...]
+    "g_E_properties_order": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.AddV("person").Property("name", 
"alice").As("a").AddE("self").From("a").To("a").Property("weight", 
0.5).Property("a", int32(10)).AddE("self").From("a").To("a").Property("weight", 
1.0).Property("a", int32(11)).AddE("self").From("a").To("a").Property("weight", 
0.4).Property("a", int32(12)).AddE("self").From("a").To("a").Property("weight", 
1.0).Property("a", int [...]
+    "g_E_properties_order_byXdescX": {func(g *gremlingo.GraphTraversalSource, 
p map[string]interface{}) *gremlingo.GraphTraversal {return 
g.AddV("person").Property("name", 
"alice").As("a").AddE("self").From("a").To("a").Property("weight", 
0.5).Property("a", int32(10)).AddE("self").From("a").To("a").Property("weight", 
1.0).Property("a", int32(11)).AddE("self").From("a").To("a").Property("weight", 
0.4).Property("a", int32(12)).AddE("self").From("a").To("a").Property("weight", 
1.0).Property [...]
     "g_inject_order": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject("zzz", 
"foo", uuid.MustParse("6100808b-62f9-42b7-957e-ed66c30f40d1"), 
[]interface{}{"a", "b", "c", "d"}, 1, time.Date(2023, 8, 1, 0, 0, 0, 0, 
time.FixedZone("UTC+00:00", 0)), []interface{}{"a", "b", "c"}, 
map[interface{}]interface{}{"a": "a", "b": "b" }, nil, 2.0, time.Date(2023, 1, 
1, 0, 0, 0, 0, time.FixedZone("UTC+00:00", 0)), gremlingo.NewSimpleSet("x",  
[...]
     "g_inject_order_byXdescX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject("zzz", 
"foo", uuid.MustParse("6100808b-62f9-42b7-957e-ed66c30f40d1"), 
[]interface{}{"a", "b", "c", "d"}, 1, time.Date(2023, 8, 1, 0, 0, 0, 0, 
time.FixedZone("UTC+00:00", 0)), []interface{}{"a", "b", "c"}, 
map[interface{}]interface{}{"a": "a", "b": "b" }, nil, 2.0, time.Date(2023, 1, 
1, 0, 0, 0, 0, time.FixedZone("UTC+00:00", 0)), gremlingo.NewSimple [...]
     "g_V_out_out_order_byXascX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V().Out().Out().Order().By(gremlingo.Order.Asc)}}, 
diff --git 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
index 4af404f05a..d7d5e2e56d 100644
--- 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
+++ 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
@@ -1145,9 +1145,8 @@ const gremlins = {
     g_E: [function({g}) { return g.E() }], 
     g_EX11X: [function({g, eid11}) { return g.E(eid11) }], 
     g_EX11AsStringX: [function({g, eid11}) { return g.E(eid11) }], 
-    g_EXe11X: [function({g, e11}) { return g.E(e11) }], 
-    g_EXe7_e11X: [function({g, e7, e11}) { return g.E(e7, e11) }], 
-    g_EXlistXe7_e11XX: [function({g, xx1}) { return g.E(xx1) }], 
+    g_EXeid7_eid11X: [function({g, eid11, eid7}) { return g.E(eid7, eid11) }], 
+    g_EXlistXeid7_eid11XX: [function({g, xx1}) { return g.E(xx1) }], 
     g_EXnullX: [function({g}) { return g.E(null) }], 
     g_EXlistXnullXX: [function({g, xx1}) { return g.E(xx1) }], 
     g_EX11_nullX: [function({g, eid11}) { return g.E(eid11, null) }], 
@@ -1556,6 +1555,10 @@ const gremlins = {
     g_V_hasXageX_propertiesXage_nameX_value: [function({g}) { return 
g.V().has("age").properties("age", "name").value() }], 
     g_V_propertiesXname_age_nullX_value: [function({g}) { return 
g.V().properties("name", "age", null).value() }], 
     g_V_valuesXname_age_nullX: [function({g}) { return g.V().values("name", 
"age", null) }], 
+    g_E_propertiesXweightX: [function({g}) { return g.E().properties("weight") 
}], 
+    g_E_properties: [function({g}) { return g.addV("person").property("name", 
"alice").as("a").addV("person").property("name", 
"bob").as("b").addE("knows").from_("a").to("b").property("weight", 
0.5).property("since", 2020) }, function({g}) { return g.E().properties() }], 
+    g_E_propertiesXsinceX: [function({g}) { return 
g.addV("person").property("name", 
"alice").as("a").addV("person").property("name", 
"bob").as("b").addE("knows").from_("a").to("b").property("weight", 
0.5).property("since", 2020) }, function({g}) { return 
g.E().properties("since") }], 
+    g_E_properties_multi_edges: [function({g}) { return 
g.addV("person").property("name", 
"alice").as("a").addV("person").property("name", 
"bob").as("b").addE("knows").from_("a").to("b").property("weight", 
0.5).property("since", 
2020).addE("likes").from_("a").to("b").property("weight", 1.0).property("tag", 
"friend") }, function({g}) { return g.E().properties() }], 
     g_injectX__feature___test__nullX_rTrim: [function({g}) { return 
g.inject("feature  ", "one test ", null, "", " ", " abc", "abc ", " abc ", "  
").rTrim() }], 
     g_injectX__feature___test__nullX_rTrimXlocalX: [function({g}) { return 
g.inject(["  feature  ", " one test ", null, "", " ", " abc", "abc ", " abc ", 
"  "]).rTrim(Scope.local) }], 
     g_injectX__feature__X_rTrim: [function({g}) { return g.inject("  feature  
").rTrim() }], 
@@ -1926,6 +1929,8 @@ const gremlins = {
     g_V_properties_order_id: [function({g}) { return 
g.V().properties().order().id() }], 
     g_E_properties_order_value: [function({g}) { return 
g.addV("person").property("name", 
"alice").as("a").addE("self").from_("a").to("a").property("weight", 
0.5).property("a", 10).addE("self").from_("a").to("a").property("weight", 
1.0).property("a", 11).addE("self").from_("a").to("a").property("weight", 
0.4).property("a", 12).addE("self").from_("a").to("a").property("weight", 
1.0).property("a", 13).addE("self").from_("a").to("a").property("weight", 
0.4).property("a", 14).addE("self").fr [...]
     g_E_properties_order_byXdescX_value: [function({g}) { return 
g.addV("person").property("name", 
"alice").as("a").addE("self").from_("a").to("a").property("weight", 
0.5).property("a", 10).addE("self").from_("a").to("a").property("weight", 
1.0).property("a", 11).addE("self").from_("a").to("a").property("weight", 
0.4).property("a", 12).addE("self").from_("a").to("a").property("weight", 
1.0).property("a", 13).addE("self").from_("a").to("a").property("weight", 
0.4).property("a", 14).addE(" [...]
+    g_E_properties_order: [function({g}) { return 
g.addV("person").property("name", 
"alice").as("a").addE("self").from_("a").to("a").property("weight", 
0.5).property("a", 10).addE("self").from_("a").to("a").property("weight", 
1.0).property("a", 11).addE("self").from_("a").to("a").property("weight", 
0.4).property("a", 12).addE("self").from_("a").to("a").property("weight", 
1.0).property("a", 13).addE("self").from_("a").to("a").property("weight", 
0.4).property("a", 14).addE("self").from_("a [...]
+    g_E_properties_order_byXdescX: [function({g}) { return 
g.addV("person").property("name", 
"alice").as("a").addE("self").from_("a").to("a").property("weight", 
0.5).property("a", 10).addE("self").from_("a").to("a").property("weight", 
1.0).property("a", 11).addE("self").from_("a").to("a").property("weight", 
0.4).property("a", 12).addE("self").from_("a").to("a").property("weight", 
1.0).property("a", 13).addE("self").from_("a").to("a").property("weight", 
0.4).property("a", 14).addE("self") [...]
     g_inject_order: [function({g}) { return g.inject("zzz", "foo", 
uuid.parse("6100808b-62f9-42b7-957e-ed66c30f40d1"), ["a", "b", "c", "d"], 1, 
new Date('2023-08-01T00:00Z'), ["a", "b", "c"], new Map([["a", "a"], ["b", 
"b"]]), null, 2.0, new Date('2023-01-01T00:00Z'), new Set(["x", "y", "z"]), new 
Map([["a", "a"], ["b", false], ["c", "c"]]), "bar", 
uuid.parse("5100808b-62f9-42b7-957e-ed66c30f40d1"), true, false, 
Number.POSITIVE_INFINITY, Number.NaN, Number.NEGATIVE_INFINITY).order() }], 
     g_inject_order_byXdescX: [function({g}) { return g.inject("zzz", "foo", 
uuid.parse("6100808b-62f9-42b7-957e-ed66c30f40d1"), ["a", "b", "c", "d"], 1, 
new Date('2023-08-01T00:00Z'), ["a", "b", "c"], new Map([["a", "a"], ["b", 
"b"]]), null, 2.0, new Date('2023-01-01T00:00Z'), new Set(["x", "y", "z"]), new 
Map([["a", "a"], ["b", false], ["c", "c"]]), "bar", 
uuid.parse("5100808b-62f9-42b7-957e-ed66c30f40d1"), true, false, 
Number.POSITIVE_INFINITY, Number.NaN, Number.NEGATIVE_INFINITY).ord [...]
     g_V_out_out_order_byXascX: [function({g}) { return 
g.V().out().out().order().by(Order.asc) }], 
diff --git a/gremlin-python/src/main/python/tests/feature/feature_steps.py 
b/gremlin-python/src/main/python/tests/feature/feature_steps.py
index f586e47918..d669923b12 100644
--- a/gremlin-python/src/main/python/tests/feature/feature_steps.py
+++ b/gremlin-python/src/main/python/tests/feature/feature_steps.py
@@ -369,6 +369,12 @@ def _convert(val, ctx):
         return __find_cached_element(ctx, graph_name, val[2:-1], "e")
     elif isinstance(val, str) and re.match(r"^vp\[.*\]$", val):  # parse 
vertexproperty
         return __find_cached_element(ctx, graph_name, val[3:-1], "vp")
+    elif isinstance(val, str) and re.match(r"^prop\[.+\]$", val):  # parse 
property as key/value pair
+        inner = val[5:-1]
+        comma_idx = inner.index(",")
+        key = inner[:comma_idx]
+        value = _convert(inner[comma_idx + 1:], ctx)
+        return Property(key, value, None)
     elif isinstance(val, str) and re.match(r"^m\[.*\]$", val):  # parse json 
as a map
         return _convert(json.loads(val[2:-1]), ctx)
     elif isinstance(val, str) and re.match(r"^p\[.*\]$", val):  # parse path
@@ -438,6 +444,9 @@ def _convert_results(val):
     if isinstance(val, Path):
         # kill out labels as they aren't in the assertion logic
         return Path([set([])], val.objects)
+    elif isinstance(val, Property) and not isinstance(val, VertexProperty):
+        # strip element for key/value only comparison with prop[...] syntax
+        return Property(val.key, val.value, None)
     elif _is_nan(val):
         # we need to use the string form for NaN to test the results since 
float.nan != float.nan
         return "d[NaN]"
diff --git a/gremlin-python/src/main/python/tests/feature/gremlin.py 
b/gremlin-python/src/main/python/tests/feature/gremlin.py
index aad2a75ca9..cf19d6d85c 100644
--- a/gremlin-python/src/main/python/tests/feature/gremlin.py
+++ b/gremlin-python/src/main/python/tests/feature/gremlin.py
@@ -1117,9 +1117,8 @@ world.gremlins = {
     'g_E': [(lambda g:g.E())], 
     'g_EX11X': [(lambda g, eid11=None:g.E(eid11))], 
     'g_EX11AsStringX': [(lambda g, eid11=None:g.E(eid11))], 
-    'g_EXe11X': [(lambda g, e11=None:g.E(e11))], 
-    'g_EXe7_e11X': [(lambda g, e7=None,e11=None:g.E(e7, e11))], 
-    'g_EXlistXe7_e11XX': [(lambda g, xx1=None:g.E(xx1))], 
+    'g_EXeid7_eid11X': [(lambda g, eid11=None,eid7=None:g.E(eid7, eid11))], 
+    'g_EXlistXeid7_eid11XX': [(lambda g, xx1=None:g.E(xx1))], 
     'g_EXnullX': [(lambda g:g.E(None))], 
     'g_EXlistXnullXX': [(lambda g, xx1=None:g.E(xx1))], 
     'g_EX11_nullX': [(lambda g, eid11=None:g.E(eid11, None))], 
@@ -1528,6 +1527,10 @@ world.gremlins = {
     'g_V_hasXageX_propertiesXage_nameX_value': [(lambda 
g:g.V().has('age').properties('age', 'name').value())], 
     'g_V_propertiesXname_age_nullX_value': [(lambda g:g.V().properties('name', 
'age', None).value())], 
     'g_V_valuesXname_age_nullX': [(lambda g:g.V().values('name', 'age', 
None))], 
+    'g_E_propertiesXweightX': [(lambda g:g.E().properties('weight'))], 
+    'g_E_properties': [(lambda g:g.add_v('person').property('name', 
'alice').as_('a').add_v('person').property('name', 
'bob').as_('b').add_e('knows').from_('a').to('b').property('weight', 
0.5).property('since', 2020)), (lambda g:g.E().properties())], 
+    'g_E_propertiesXsinceX': [(lambda g:g.add_v('person').property('name', 
'alice').as_('a').add_v('person').property('name', 
'bob').as_('b').add_e('knows').from_('a').to('b').property('weight', 
0.5).property('since', 2020)), (lambda g:g.E().properties('since'))], 
+    'g_E_properties_multi_edges': [(lambda 
g:g.add_v('person').property('name', 
'alice').as_('a').add_v('person').property('name', 
'bob').as_('b').add_e('knows').from_('a').to('b').property('weight', 
0.5).property('since', 
2020).add_e('likes').from_('a').to('b').property('weight', 1.0).property('tag', 
'friend')), (lambda g:g.E().properties())], 
     'g_injectX__feature___test__nullX_rTrim': [(lambda g:g.inject('feature  ', 
'one test ', None, '', ' ', ' abc', 'abc ', ' abc ', '  ').r_trim())], 
     'g_injectX__feature___test__nullX_rTrimXlocalX': [(lambda g:g.inject(['  
feature  ', ' one test ', None, '', ' ', ' abc', 'abc ', ' abc ', '  
']).r_trim(Scope.local))], 
     'g_injectX__feature__X_rTrim': [(lambda g:g.inject('  feature  
').r_trim())], 
@@ -1898,6 +1901,8 @@ world.gremlins = {
     'g_V_properties_order_id': [(lambda g:g.V().properties().order().id_())], 
     'g_E_properties_order_value': [(lambda 
g:g.add_v('person').property('name', 
'alice').as_('a').add_e('self').from_('a').to('a').property('weight', 
0.5).property('a', 10).add_e('self').from_('a').to('a').property('weight', 
1.0).property('a', 11).add_e('self').from_('a').to('a').property('weight', 
0.4).property('a', 12).add_e('self').from_('a').to('a').property('weight', 
1.0).property('a', 13).add_e('self').from_('a').to('a').property('weight', 
0.4).property('a', 14).add_e('self').from_ [...]
     'g_E_properties_order_byXdescX_value': [(lambda 
g:g.add_v('person').property('name', 
'alice').as_('a').add_e('self').from_('a').to('a').property('weight', 
0.5).property('a', 10).add_e('self').from_('a').to('a').property('weight', 
1.0).property('a', 11).add_e('self').from_('a').to('a').property('weight', 
0.4).property('a', 12).add_e('self').from_('a').to('a').property('weight', 
1.0).property('a', 13).add_e('self').from_('a').to('a').property('weight', 
0.4).property('a', 14).add_e('sel [...]
+    'g_E_properties_order': [(lambda g:g.add_v('person').property('name', 
'alice').as_('a').add_e('self').from_('a').to('a').property('weight', 
0.5).property('a', 10).add_e('self').from_('a').to('a').property('weight', 
1.0).property('a', 11).add_e('self').from_('a').to('a').property('weight', 
0.4).property('a', 12).add_e('self').from_('a').to('a').property('weight', 
1.0).property('a', 13).add_e('self').from_('a').to('a').property('weight', 
0.4).property('a', 14).add_e('self').from_('a'). [...]
+    'g_E_properties_order_byXdescX': [(lambda 
g:g.add_v('person').property('name', 
'alice').as_('a').add_e('self').from_('a').to('a').property('weight', 
0.5).property('a', 10).add_e('self').from_('a').to('a').property('weight', 
1.0).property('a', 11).add_e('self').from_('a').to('a').property('weight', 
0.4).property('a', 12).add_e('self').from_('a').to('a').property('weight', 
1.0).property('a', 13).add_e('self').from_('a').to('a').property('weight', 
0.4).property('a', 14).add_e('self').fr [...]
     'g_inject_order': [(lambda g:g.inject('zzz', 'foo', 
uuid.UUID('6100808b-62f9-42b7-957e-ed66c30f40d1'), ['a', 'b', 'c', 'd'], 1, 
datetime.datetime.fromisoformat('2023-08-01T00:00+00:00'), ['a', 'b', 'c'], { 
'a': 'a', 'b': 'b' }, None, 2.0, 
datetime.datetime.fromisoformat('2023-01-01T00:00+00:00'), {'x', 'y', 'z'}, { 
'a': 'a', 'b': False, 'c': 'c' }, 'bar', 
uuid.UUID('5100808b-62f9-42b7-957e-ed66c30f40d1'), True, False, float('inf'), 
float('nan'), float('-inf')).order())], 
     'g_inject_order_byXdescX': [(lambda g:g.inject('zzz', 'foo', 
uuid.UUID('6100808b-62f9-42b7-957e-ed66c30f40d1'), ['a', 'b', 'c', 'd'], 1, 
datetime.datetime.fromisoformat('2023-08-01T00:00+00:00'), ['a', 'b', 'c'], { 
'a': 'a', 'b': 'b' }, None, 2.0, 
datetime.datetime.fromisoformat('2023-01-01T00:00+00:00'), {'x', 'y', 'z'}, { 
'a': 'a', 'b': False, 'c': 'c' }, 'bar', 
uuid.UUID('5100808b-62f9-42b7-957e-ed66c30f40d1'), True, False, float('inf'), 
float('nan'), float('-inf')).order().by(Ord [...]
     'g_V_out_out_order_byXascX': [(lambda 
g:g.V().out().out().order().by(Order.asc))], 
diff --git 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
index a8dfa900da..3b1912556b 100644
--- 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
+++ 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
@@ -167,11 +167,6 @@ public final class StepDefinition {
 
         add(Pair.with(Pattern.compile("v\\[(.+)\\]\\.id"), s -> 
world.convertIdToScript(g.V().has("name", s).id().next(), Vertex.class)));
         add(Pair.with(Pattern.compile("v\\[(.+)\\]\\.sid"), s -> 
world.convertIdToScript(g.V().has("name", s).id().next(), Vertex.class)));
-        add(Pair.with(Pattern.compile("v\\[(.+)\\]"), s -> {
-            final Iterator<Object> itty = g.V().has("name", s).id();
-            return String.format("new Vertex(%s,\"%s\")", itty.hasNext() ?
-                    world.convertIdToScript(itty.next(), Vertex.class) : s, 
Vertex.DEFAULT_LABEL);
-        }));
         add(Pair.with(Pattern.compile("e\\[(.+)\\]\\.id"), s -> 
world.convertIdToScript(getEdgeId(g, s), Edge.class)));
         add(Pair.with(Pattern.compile("e\\[(.+)\\]\\.sid"), s -> 
world.convertIdToScript(getEdgeId(g, s), Edge.class)));
         add(Pair.with(Pattern.compile("t\\[(.*)\\]"), s -> 
String.format("T.%s", s)));
@@ -180,15 +175,6 @@ public final class StepDefinition {
         add(Pair.with(Pattern.compile("(null)"), s -> "null"));
         add(Pair.with(Pattern.compile("(true)"), s -> "true"));
         add(Pair.with(Pattern.compile("(false)"), s -> "false"));
-
-        // the following force ignore conditions as they cannot be parsed by 
the grammar at this time. the grammar will
-        // need to be modified to handle them or perhaps these tests stay 
relegated to the JVM in some way
-        add(Pair.with(Pattern.compile("e\\[(.+)\\]"), s -> {
-            throw new AssumptionViolatedException("This test uses a Edge as a 
parameter which is not supported by gremlin-language");
-        }));
-        add(Pair.with(Pattern.compile("p\\[(.*)\\]"), s -> {
-            throw new AssumptionViolatedException("This test uses a Path as a 
parameter which is not supported by gremlin-language");
-        }));
     }};
 
     private List<Pair<Pattern, Function<String,Object>>> 
objectMatcherConverters = new ArrayList<Pair<Pattern, 
Function<String,Object>>>() {{
@@ -218,10 +204,13 @@ public final class StepDefinition {
         // return the string values as is, used to wrap results that may 
contain other regex patterns
         add(Pair.with(Pattern.compile("str\\[(.*)\\]"), String::valueOf));
 
-        /*
-         * TODO FIXME Add same support for other languages (js, python, .net)
-         */
         add(Pair.with(Pattern.compile("vp\\[(.+)\\]"), s -> 
getVertexProperty(g, s)));
+        add(Pair.with(Pattern.compile("prop\\[(.+)\\]"), s -> {
+            final int commaIdx = s.indexOf(",");
+            final String key = s.substring(0, commaIdx);
+            final Object value = convertToObject(s.substring(commaIdx + 1));
+            return Pair.with(key, value);
+        }));
 
         add(Pair.with(Pattern.compile("p\\[(.*)\\]"), s -> {
             final String[] items = s.split(",");
@@ -652,6 +641,8 @@ public final class StepDefinition {
                 return new LinkedHashMap() {{
                     put(((Map.Entry<?, ?>) o).getKey(), ((Map.Entry<?, ?>) 
o).getValue());
                 }};
+            } else if (o instanceof Property && !(o instanceof 
VertexProperty)) {
+                return Pair.with(((Property) o).key(), ((Property) o).value());
             } else {
                 return o;
             }
diff --git 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature
 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature
index 3bab88cc1e..0736def307 100644
--- 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature
+++ 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature
@@ -58,25 +58,13 @@ Feature: Step - E(), inV(), outV(), bothV(), otherV()
       | result |
       | e[josh-created->lop] |
 
-  Scenario: g_EXe11X
+  Scenario: g_EXeid7_eid11X
     Given the modern graph
-    And using the parameter e11 defined as "e[josh-created->lop]"
-    And the traversal of
-      """
-      g.E(e11)
-      """
-    When iterated to list
-    Then the result should be unordered
-      | result |
-      | e[josh-created->lop] |
-
-  Scenario: g_EXe7_e11X
-    Given the modern graph
-    And using the parameter e7 defined as "e[marko-knows->vadas]"
-    And using the parameter e11 defined as "e[josh-created->lop]"
+    And using the parameter eid7 defined as "e[marko-knows->vadas].id"
+    And using the parameter eid11 defined as "e[josh-created->lop].id"
     And the traversal of
       """
-      g.E(e7,e11)
+      g.E(eid7,eid11)
       """
     When iterated to list
     Then the result should be unordered
@@ -84,9 +72,9 @@ Feature: Step - E(), inV(), outV(), bothV(), otherV()
       | e[marko-knows->vadas] |
       | e[josh-created->lop] |
 
-  Scenario: g_EXlistXe7_e11XX
+  Scenario: g_EXlistXeid7_eid11XX
     Given the modern graph
-    And using the parameter xx1 defined as 
"l[e[marko-knows->vadas],e[josh-created->lop]]"
+    And using the parameter xx1 defined as 
"l[e[marko-knows->vadas].id,e[josh-created->lop].id]"
     And the traversal of
       """
       g.E(xx1)
diff --git 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Properties.feature
 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Properties.feature
index cf672397e2..c87ac1654d 100644
--- 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Properties.feature
+++ 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Properties.feature
@@ -108,23 +108,74 @@ Feature: Step - properties()
       | lop |
       | ripple |
 
-  Scenario: g_injectXg_VX1X_propertiesXnameX_nextX_value
-    Given an unsupported test
-    Then nothing should happen because
+  Scenario: g_E_propertiesXweightX
+    Given the modern graph
+    And the traversal of
       """
-      The test suite doesn't do well with vertex property values.
+      g.E().properties("weight")
       """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | prop[weight,d[0.2].d] |
+      | prop[weight,d[0.4].d] |
+      | prop[weight,d[0.4].d] |
+      | prop[weight,d[0.5].d] |
+      | prop[weight,d[1.0].d] |
+      | prop[weight,d[1.0].d] |
 
-  Scenario: g_V_hasXageX_properties_hasXid_nameIdX_value
-    Given an unsupported test
-    Then nothing should happen because
+  Scenario: g_E_properties
+    Given the empty graph
+    And the graph initializer of
+      """
+      g.addV("person").property("name","alice").as("a").
+        addV("person").property("name","bob").as("b").
+        addE("knows").from("a").to("b").property("weight", 
0.5d).property("since", 2020i)
+      """
+    And the traversal of
       """
-      GLV suite doesn't support property identifiers and related assertions
+      g.E().properties()
       """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | prop[weight,d[0.5].d] |
+      | prop[since,d[2020].i] |
 
-  Scenario: g_V_hasXageX_properties_hasXid_nameIdAsStringX_value
-    Given an unsupported test
-    Then nothing should happen because
+  Scenario: g_E_propertiesXsinceX
+    Given the empty graph
+    And the graph initializer of
+      """
+      g.addV("person").property("name","alice").as("a").
+        addV("person").property("name","bob").as("b").
+        addE("knows").from("a").to("b").property("weight", 
0.5d).property("since", 2020i)
+      """
+    And the traversal of
       """
-      GLV suite doesn't support property identifiers and related assertions
-      """
\ No newline at end of file
+      g.E().properties("since")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | prop[since,d[2020].i] |
+
+  Scenario: g_E_properties_multi_edges
+    Given the empty graph
+    And the graph initializer of
+      """
+      g.addV("person").property("name","alice").as("a").
+        addV("person").property("name","bob").as("b").
+        addE("knows").from("a").to("b").property("weight", 
0.5d).property("since", 2020i).
+        addE("likes").from("a").to("b").property("weight", 
1.0d).property("tag", "friend")
+      """
+    And the traversal of
+      """
+      g.E().properties()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | prop[weight,d[0.5].d] |
+      | prop[since,d[2020].i] |
+      | prop[weight,d[1.0].d] |
+      | prop[tag,friend] |
\ No newline at end of file
diff --git 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/semantics/Orderability.feature
 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/semantics/Orderability.feature
index 0079aac13f..5f99974a06 100644
--- 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/semantics/Orderability.feature
+++ 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/semantics/Orderability.feature
@@ -150,6 +150,70 @@ Feature: Orderability
       | d[11].i |
       | d[10].i |
 
+  Scenario: g_E_properties_order
+    Given the empty graph
+    And the graph initializer of
+      """
+      g.addV("person").property("name", "alice").as("a").
+        addE("self").from("a").to("a").property("weight", 0.5d).property("a", 
10i).
+        addE("self").from("a").to("a").property("weight", 1.0d).property("a", 
11i).
+        addE("self").from("a").to("a").property("weight", 0.4d).property("a", 
12i).
+        addE("self").from("a").to("a").property("weight", 1.0d).property("a", 
13i).
+        addE("self").from("a").to("a").property("weight", 0.4d).property("a", 
14i).
+        addE("self").from("a").to("a").property("weight", 0.2d).property("a", 
15i)
+      """
+    And the traversal of
+      """
+      g.E().properties().order()
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | prop[a,d[10].i] |
+      | prop[a,d[11].i] |
+      | prop[a,d[12].i] |
+      | prop[a,d[13].i] |
+      | prop[a,d[14].i] |
+      | prop[a,d[15].i] |
+      | prop[weight,d[0.2].d] |
+      | prop[weight,d[0.4].d] |
+      | prop[weight,d[0.4].d] |
+      | prop[weight,d[0.5].d] |
+      | prop[weight,d[1.0].d] |
+      | prop[weight,d[1.0].d] |
+
+  Scenario: g_E_properties_order_byXdescX
+    Given the empty graph
+    And the graph initializer of
+      """
+      g.addV("person").property("name", "alice").as("a").
+        addE("self").from("a").to("a").property("weight", 0.5d).property("a", 
10i).
+        addE("self").from("a").to("a").property("weight", 1.0d).property("a", 
11i).
+        addE("self").from("a").to("a").property("weight", 0.4d).property("a", 
12i).
+        addE("self").from("a").to("a").property("weight", 1.0d).property("a", 
13i).
+        addE("self").from("a").to("a").property("weight", 0.4d).property("a", 
14i).
+        addE("self").from("a").to("a").property("weight", 0.2d).property("a", 
15i)
+      """
+    And the traversal of
+      """
+      g.E().properties().order().by(desc)
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | prop[weight,d[1.0].d] |
+      | prop[weight,d[1.0].d] |
+      | prop[weight,d[0.5].d] |
+      | prop[weight,d[0.4].d] |
+      | prop[weight,d[0.4].d] |
+      | prop[weight,d[0.2].d] |
+      | prop[a,d[15].i] |
+      | prop[a,d[14].i] |
+      | prop[a,d[13].i] |
+      | prop[a,d[12].i] |
+      | prop[a,d[11].i] |
+      | prop[a,d[10].i] |
+
   @GraphComputerVerificationInjectionNotSupported
   Scenario: g_inject_order
     Given the empty graph


Reply via email to