@@ -3362,6 +3362,83 @@ def test_empty_stack(self, r):
3362
3362
result = p .execute ()
3363
3363
assert result == []
3364
3364
3365
+ @pytest .mark .onlycluster
3366
+ def test_exec_error_in_response (self , r ):
3367
+ """
3368
+ an invalid pipeline command at exec time adds the exception instance
3369
+ to the list of returned values
3370
+ """
3371
+ hashkey = "{key}"
3372
+ r [f"{ hashkey } :c" ] = "a"
3373
+ with r .pipeline () as pipe :
3374
+ pipe .set (f"{ hashkey } :a" , 1 ).set (f"{ hashkey } :b" , 2 )
3375
+ pipe .lpush (f"{ hashkey } :c" , 3 ).set (f"{ hashkey } :d" , 4 )
3376
+ result = pipe .execute (raise_on_error = False )
3377
+
3378
+ assert result [0 ]
3379
+ assert r [f"{ hashkey } :a" ] == b"1"
3380
+ assert result [1 ]
3381
+ assert r [f"{ hashkey } :b" ] == b"2"
3382
+
3383
+ # we can't lpush to a key that's a string value, so this should
3384
+ # be a ResponseError exception
3385
+ assert isinstance (result [2 ], redis .ResponseError )
3386
+ assert r [f"{ hashkey } :c" ] == b"a"
3387
+
3388
+ # since this isn't a transaction, the other commands after the
3389
+ # error are still executed
3390
+ assert result [3 ]
3391
+ assert r [f"{ hashkey } :d" ] == b"4"
3392
+
3393
+ # make sure the pipe was restored to a working state
3394
+ assert pipe .set (f"{ hashkey } :z" , "zzz" ).execute () == [True ]
3395
+ assert r [f"{ hashkey } :z" ] == b"zzz"
3396
+
3397
+ def test_exec_error_in_no_transaction_pipeline (self , r ):
3398
+ r ["a" ] = 1
3399
+ with r .pipeline (transaction = False ) as pipe :
3400
+ pipe .llen ("a" )
3401
+ pipe .expire ("a" , 100 )
3402
+
3403
+ with pytest .raises (redis .ResponseError ) as ex :
3404
+ pipe .execute ()
3405
+
3406
+ assert str (ex .value ).startswith (
3407
+ "Command # 1 (LLEN a) of pipeline caused error: "
3408
+ )
3409
+
3410
+ assert r ["a" ] == b"1"
3411
+
3412
+ @pytest .mark .onlycluster
3413
+ @skip_if_server_version_lt ("2.0.0" )
3414
+ def test_pipeline_discard (self , r ):
3415
+ hashkey = "{key}"
3416
+
3417
+ # empty pipeline should raise an error
3418
+ with r .pipeline () as pipe :
3419
+ pipe .set (f"{ hashkey } :key" , "someval" )
3420
+ with pytest .raises (redis .exceptions .RedisClusterException ) as ex :
3421
+ pipe .discard ()
3422
+
3423
+ assert str (ex .value ).startswith ("method discard() is not supported outside of transactional context" )
3424
+
3425
+ # setting a pipeline and discarding should do the same
3426
+ with r .pipeline () as pipe :
3427
+ pipe .set (f"{ hashkey } :key" , "someval" )
3428
+ pipe .set (f"{ hashkey } :someotherkey" , "val" )
3429
+ response = pipe .execute ()
3430
+ pipe .set (f"{ hashkey } :key" , "another value!" )
3431
+ with pytest .raises (redis .exceptions .RedisClusterException ) as ex :
3432
+ pipe .discard ()
3433
+
3434
+ assert str (ex .value ).startswith ("method discard() is not supported outside of transactional context" )
3435
+
3436
+ pipe .set (f"{ hashkey } :foo" , "bar" )
3437
+ response = pipe .execute ()
3438
+
3439
+ assert response [0 ]
3440
+ assert r .get (f"{ hashkey } :foo" ) == b"bar"
3441
+
3365
3442
3366
3443
@pytest .mark .onlycluster
3367
3444
class TestReadOnlyPipeline :
0 commit comments