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

Cole-Greer pushed a commit to branch 3.8-dev
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit fe2abf26280e56e45872d4e17fd73baef41fa4c2
Merge: e8f41c81b9 5349dbb89d
Author: Cole Greer <[email protected]>
AuthorDate: Wed Jul 22 17:02:16 2026 -0700

    Merge branch '3.7-dev' into 3.8-dev

 CHANGELOG.asciidoc                                 |  5 ++++
 docs/src/upgrade/release-3.7.x.asciidoc            |  9 +++++++
 .../optimization/ProductiveByStrategy.java         |  3 +++
 .../Strategy/Optimization/ProductiveByStrategy.cs  |  2 ++
 gremlin-go/driver/strategies.go                    |  7 ++++-
 gremlin-go/driver/strategies_test.go               | 31 ++++++++++++++++++++++
 .../lib/process/traversal-strategy.js              |  4 +++
 .../python/gremlin_python/process/strategies.py    |  7 +++++
 .../python/gremlin_python/process/traversal.py     |  2 +-
 .../python/tests/unit/process/test_strategies.py   | 12 +++++++++
 10 files changed, 80 insertions(+), 2 deletions(-)

diff --cc gremlin-go/driver/strategies.go
index 076b22f14b,f03a00f01f..88c1785f12
--- a/gremlin-go/driver/strategies.go
+++ b/gremlin-go/driver/strategies.go
@@@ -420,11 -364,12 +420,14 @@@ func PathRetractionStrategy() Traversal
  // the initial Traversal argument or null. In this way, the By() is always 
"productive". This strategy
  // is an "optimization" but it is perhaps more of a "decoration", but it 
should follow
  // ByModulatorOptimizationStrategy which features optimizations relevant to 
this one.
+ //
+ // Deprecated: As of release 3.7.7, not replaced. This strategy was added as 
a temporary way to mimic
+ // pre-3.5.0 null processing behavior.
 -func ProductiveByStrategy(config ProductiveByStrategyConfig) 
TraversalStrategy {
 +func ProductiveByStrategy(config ...ProductiveByStrategyConfig) 
TraversalStrategy {
        configMap := make(map[string]interface{})
 -      configMap["productiveKeys"] = config.ProductiveKeys
 +      if len(config) > 0 {
 +              configMap["productiveKeys"] = config[0].ProductiveKeys
 +      }
  
        return &traversalStrategy{name: optimizationNamespace + 
"ProductiveByStrategy", configuration: configMap}
  }
diff --cc gremlin-go/driver/strategies_test.go
index 4946a74303,395b50fd71..d09e59add2
--- a/gremlin-go/driver/strategies_test.go
+++ b/gremlin-go/driver/strategies_test.go
@@@ -413,18 -413,35 +413,49 @@@ func TestStrategy(t *testing.T) 
                assert.Nil(t, err)
                assert.Equal(t, int32(6), val)
        })
 +
 +      t.Run("Test without strategies MessagePassingReductionStrategy", func(t 
*testing.T) {
 +              g := getModernGraph(t, testNoAuthUrl, &AuthInfo{}, 
&tls.Config{})
 +              defer g.remoteConnection.Close()
 +
 +              count, err := 
g.WithoutStrategies(MessagePassingReductionStrategy()).V().Count().ToList()
 +              assert.Nil(t, err)
 +              assert.NotNil(t, count)
 +              assert.Equal(t, 1, len(count))
 +              val, err := count[0].GetInt32()
 +              assert.Nil(t, err)
 +              assert.Equal(t, int32(6), val)
 +      })
 +
  }
+ 
+ func Test_StrategyConfig_partitionNilReadPartitions(t *testing.T) {
+       t.Run("Test PartitionStrategy with nil ReadPartitions does not panic", 
func(t *testing.T) {
+               config := PartitionStrategyConfig{
+                       PartitionKey:   "partition",
+                       WritePartition: "write",
+                       // ReadPartitions intentionally left unset (nil 
interface).
+               }
+               var strategy TraversalStrategy
+               assert.NotPanics(t, func() {
+                       strategy = PartitionStrategy(config)
+               })
+               assert.NotNil(t, strategy)
+               configMap := strategy.(*traversalStrategy).configuration
+               _, ok := configMap["readPartitions"]
+               assert.False(t, ok)
+       })
+ 
+       t.Run("Test PartitionStrategy with non-empty ReadPartitions sets 
readPartitions", func(t *testing.T) {
+               config := PartitionStrategyConfig{
+                       PartitionKey:   "partition",
+                       WritePartition: "write",
+                       ReadPartitions: NewSimpleSet("read"),
+               }
+               strategy := PartitionStrategy(config)
+               assert.NotNil(t, strategy)
+               configMap := strategy.(*traversalStrategy).configuration
+               _, ok := configMap["readPartitions"]
+               assert.True(t, ok)
+       })
+ }
diff --cc 
gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal-strategy.js
index 51e992716f,f673d46d58..b83acfba6f
--- 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal-strategy.js
+++ 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal-strategy.js
@@@ -276,17 -243,6 +276,21 @@@ class PathRetractionStrategy extends Tr
    }
  }
  
++/**
++ * @deprecated As of release 3.7.7, not replaced. This strategy was added as 
a temporary way to mimic pre-3.5.0
++ * null processing behavior.
++ */
 +class ProductiveByStrategy extends TraversalStrategy {
 +  /**
 +   * @param {Object} [options]
 +   * @param {Array<String>} productiveKeys set of keys that will always be 
productive
 +   */
 +  constructor({ productiveKeys = [] } = {}) {
 +    
super('org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy');
 +    this.configuration['productiveKeys'] = productiveKeys;
 +  }
 +}
 +
  class CountStrategy extends TraversalStrategy {
    constructor() {
      
super('org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy');
diff --cc gremlin-python/src/main/python/gremlin_python/process/strategies.py
index 6aceb61edd,5ebbe98405..5dc7889d79
--- a/gremlin-python/src/main/python/gremlin_python/process/strategies.py
+++ b/gremlin-python/src/main/python/gremlin_python/process/strategies.py
@@@ -19,7 -19,8 +19,8 @@@
  
  __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
  
 -from gremlin_python.process.traversal import TraversalStrategy
 +from .traversal import TraversalStrategy
+ import warnings
  
  base_namespace = 'org.apache.tinkerpop.gremlin.process.traversal.strategy.'
  decoration_namespace = base_namespace + 'decoration.'
diff --cc gremlin-python/src/main/python/tests/unit/process/test_strategies.py
index adf8bcd586,1f8846e833..05d565e941
--- a/gremlin-python/src/main/python/tests/unit/process/test_strategies.py
+++ b/gremlin-python/src/main/python/tests/unit/process/test_strategies.py
@@@ -110,7 -110,19 +110,19 @@@ class TestTraversalStrategies(object)
          assert 1 == len(strategy.configuration)
          assert __.has("name","marko") == strategy.configuration["vertices"]
          ###
+         bytecode = 
g.withStrategies(ProductiveByStrategy(productiveKeys=["name", "age"])).bytecode
+         assert 1 == len(bytecode.source_instructions)
+         assert 2 == len(bytecode.source_instructions[0])
+         assert "withStrategies" == bytecode.source_instructions[0][0]
+         assert ProductiveByStrategy() == bytecode.source_instructions[0][1]
+         strategy = bytecode.source_instructions[0][1]
+         assert 1 == len(strategy.configuration)
+         assert ["name", "age"] == strategy.configuration["productiveKeys"]
+         ###
+         bytecode = g.withStrategies(ProductiveByStrategy()).bytecode
+         assert 0 == len(bytecode.source_instructions[0][1].configuration)
+         ###
 -        bytecode = g.withStrategies(OptionsStrategy(options={"x": "test", 
"y": True})).bytecode
 +        bytecode = g.withStrategies(OptionsStrategy(x="test", 
y=True)).bytecode
          assert 1 == len(bytecode.source_instructions)
          assert 2 == len(bytecode.source_instructions[0])
          assert "withStrategies" == bytecode.source_instructions[0][0]

Reply via email to