55import pytest
66
77from redis import exceptions
8+ from redis .commands .core import HashDataPersistOptions
89from tests .conftest import skip_if_server_version_lt
910from tests .test_asyncio .test_utils import redis_server_time
1011
@@ -327,7 +328,9 @@ async def test_hgetex_no_expiration(r):
327328 "b" , "foo" , "bar" , mapping = {"1" : 1 , "2" : 2 , "3" : "three" , "4" : b"four" }
328329 )
329330
330- assert await r .hgetex ("b" , "foo" , "1" , "4" ) == [b"bar" , b"1" , b"four" ]
331+ assert await r .hgetex ("b" , keys = ["foo" , "1" , "4" ]) == [b"bar" , b"1" , b"four" ]
332+ assert await r .hgetex ("b" , "foo" , keys = ["1" , "4" ]) == [b"bar" , b"1" , b"four" ]
333+ assert await r .hgetex ("b" , "foo" ) == [b"bar" ]
331334 assert await r .httl ("b" , "foo" , "1" , "4" ) == [- 1 , - 1 , - 1 ]
332335
333336
@@ -338,66 +341,76 @@ async def test_hgetex_expiration_configs(r):
338341 "test:hash" , "foo" , "bar" , mapping = {"1" : 1 , "3" : "three" , "4" : b"four" }
339342 )
340343
344+ test_keys = ["foo" , "1" , "4" ]
341345 # test get with multiple fields with expiration set through 'ex'
342- assert await r .hgetex ("test:hash" , "foo" , "1" , "4" , ex = 10 ) == [
346+ assert await r .hgetex ("test:hash" , keys = test_keys , ex = 10 ) == [
343347 b"bar" ,
344348 b"1" ,
345349 b"four" ,
346350 ]
347- assert await r .httl ("test:hash" , "foo" , "1" , "4" ) == [10 , 10 , 10 ]
351+ ttls = await r .httl ("test:hash" , * test_keys )
352+ for ttl in ttls :
353+ assert pytest .approx (ttl ) == 10
348354
349355 # test get with multiple fields removing expiration settings with 'persist'
350- assert await r .hgetex ("test:hash" , "foo" , "1" , "4" , persist = True ) == [
356+ assert await r .hgetex ("test:hash" , "foo" , keys = [ "1" , "4" ] , persist = True ) == [
351357 b"bar" ,
352358 b"1" ,
353359 b"four" ,
354360 ]
355- assert await r .httl ("test:hash" , "foo" , "1" , "4" ) == [- 1 , - 1 , - 1 ]
361+ assert await r .httl ("test:hash" , * test_keys ) == [- 1 , - 1 , - 1 ]
356362
357363 # test get with multiple fields with expiration set through 'px'
358- assert await r .hgetex ("test:hash" , "foo" , "1" , "4" , px = 6000 ) == [
364+ assert await r .hgetex ("test:hash" , keys = test_keys , px = 6000 ) == [
359365 b"bar" ,
360366 b"1" ,
361367 b"four" ,
362368 ]
363- assert await r .httl ("test:hash" , "foo" , "1" , "4" ) == [6 , 6 , 6 ]
369+ ttls = await r .httl ("test:hash" , * test_keys )
370+ for ttl in ttls :
371+ assert pytest .approx (ttl ) == 6
364372
365373 # test get single field with expiration set through 'pxat'
366374 expire_at = await redis_server_time (r ) + timedelta (minutes = 1 )
367375 assert await r .hgetex ("test:hash" , "foo" , pxat = expire_at ) == [b"bar" ]
368376 assert (await r .httl ("test:hash" , "foo" ))[0 ] <= 61
369377
378+ # test get single field with expiration set through 'exat'
379+ expire_at = await redis_server_time (r ) + timedelta (seconds = 10 )
380+ assert await r .hgetex ("test:hash" , "foo" , exat = expire_at ) == [b"bar" ]
381+ assert (await r .httl ("test:hash" , "foo" ))[0 ] <= 10
382+
370383
371384@skip_if_server_version_lt ("7.9.0" )
372- async def test_hgetex_validate_expired_foields_removed (r ):
385+ async def test_hgetex_validate_expired_fields_removed (r ):
373386 await r .delete ("test:hash" )
374387 await r .hset (
375388 "test:hash" , "foo" , "bar" , mapping = {"1" : 1 , "3" : "three" , "4" : b"four" }
376389 )
377390
378391 # test get multiple fields with expiration set
379392 # validate that expired fields are removed
380- assert await r .hgetex ("test:hash" , "foo" , "1" , "3" , ex = 1 ) == [
393+ assert await r .hgetex ("test:hash" , keys = [ "foo" , "1" , "3" ] , ex = 1 ) == [
381394 b"bar" ,
382395 b"1" ,
383396 b"three" ,
384397 ]
385398 await asyncio .sleep (1.1 )
386- assert await r .hgetex ("test:hash" , "foo" , "1" , "3" ) == [None , None , None ]
399+ assert await r .hgetex ("test:hash" , "foo" , keys = [ "1" , "3" ] ) == [None , None , None ]
387400 assert await r .httl ("test:hash" , "foo" , "1" , "3" ) == [- 2 , - 2 , - 2 ]
388401 assert await r .hgetex ("test:hash" , "4" ) == [b"four" ]
389402
390403
391404@skip_if_server_version_lt ("7.9.0" )
392405async def test_hgetex_invalid_inputs (r ):
393406 with pytest .raises (exceptions .DataError ):
394- await r .hgetex ("b" , "foo" , "1" , "3" , ex = 10 , persist = True )
407+ await r .hgetex ("b" , "foo" , ex = 10 , persist = True )
395408
396409 with pytest .raises (exceptions .DataError ):
397- await r .hgetex ("b" , "foo" , "1" , "3" , ex = 10.0 , persist = True )
410+ await r .hgetex ("b" , "foo" , ex = 10.0 , persist = True )
398411
399412 with pytest .raises (exceptions .DataError ):
400- await r .hgetex ("b" , "foo" , "1" , "3" , ex = 10 , px = 6000 )
413+ await r .hgetex ("b" , "foo" , ex = 10 , px = 6000 )
401414
402415 with pytest .raises (exceptions .DataError ):
403416 await r .hgetex ("b" , ex = 10 )
@@ -430,14 +443,12 @@ async def test_hsetex_expiration_ex_and_keepttl(r):
430443 )
431444 == 1
432445 )
433- assert await r .httl ("test:hash" , "foo" , "1" , "2" , "i1" , "i2" ) == [
434- 10 ,
435- 10 ,
436- 10 ,
437- 10 ,
438- 10 ,
439- ]
440- assert await r .hgetex ("test:hash" , "foo" , "1" , "2" , "i1" , "i2" ) == [
446+ test_keys = ["foo" , "1" , "2" , "i1" , "i2" ]
447+ ttls = await r .httl ("test:hash" , * test_keys )
448+ for ttl in ttls :
449+ assert pytest .approx (ttl ) == 10
450+
451+ assert await r .hgetex ("test:hash" , keys = test_keys ) == [
441452 b"bar" ,
442453 b"1" ,
443454 b"2" ,
@@ -447,7 +458,7 @@ async def test_hsetex_expiration_ex_and_keepttl(r):
447458 await asyncio .sleep (1.1 )
448459 # validate keepttl
449460 assert await r .hsetex ("test:hash" , "foo" , "bar1" , keepttl = True ) == 1
450- assert (await r .httl ("test:hash" , "foo" ))[0 ] < 10
461+ assert 0 < (await r .httl ("test:hash" , "foo" ))[0 ] < 10
451462
452463
453464@skip_if_server_version_lt ("7.9.0" )
@@ -459,8 +470,12 @@ async def test_hsetex_expiration_px(r):
459470 await r .hsetex ("test:hash" , "foo" , "bar" , mapping = {"1" : 1 , "2" : "2" }, px = 60000 )
460471 == 1
461472 )
462- assert await r .httl ("test:hash" , "foo" , "1" , "2" ) == [60 , 60 , 60 ]
463- assert await r .hgetex ("test:hash" , "foo" , "1" , "2" ) == [b"bar" , b"1" , b"2" ]
473+ test_keys = ["foo" , "1" , "2" ]
474+ ttls = await r .httl ("test:hash" , * test_keys )
475+ for ttl in ttls :
476+ assert pytest .approx (ttl ) == 60
477+
478+ assert await r .hgetex ("test:hash" , keys = test_keys ) == [b"bar" , b"1" , b"2" ]
464479
465480
466481@skip_if_server_version_lt ("7.9.0" )
@@ -474,30 +489,35 @@ async def test_hsetex_expiration_pxat_and_fnx(r):
474489 expire_at = await redis_server_time (r ) + timedelta (minutes = 1 )
475490 assert (
476491 await r .hsetex (
477- "test:hash" , "foo" , "bar1" , mapping = {"new" : "ok" }, pxat = expire_at , fnx = True
492+ "test:hash" ,
493+ "foo" ,
494+ "bar1" ,
495+ mapping = {"new" : "ok" },
496+ pxat = expire_at ,
497+ data_persist_option = HashDataPersistOptions .FNX ,
478498 )
479499 == 0
480500 )
481501 ttls = await r .httl ("test:hash" , "foo" , "new" )
482502 assert ttls [0 ] <= 30
483503 assert ttls [1 ] == - 2
484504
485- assert await r .hgetex ("test:hash" , "foo" , "1" , "new" ) == [b"bar" , b"1" , None ]
505+ assert await r .hgetex ("test:hash" , keys = [ "foo" , "1" , "new" ] ) == [b"bar" , b"1" , None ]
486506 assert (
487507 await r .hsetex (
488508 "test:hash" ,
489509 "foo_new" ,
490510 "bar1" ,
491511 mapping = {"new" : "ok" },
492512 pxat = expire_at ,
493- fnx = True ,
513+ data_persist_option = HashDataPersistOptions . FNX ,
494514 )
495515 == 1
496516 )
497517 ttls = await r .httl ("test:hash" , "foo" , "new" )
498518 for ttl in ttls :
499519 assert ttl <= 61
500- assert await r .hgetex ("test:hash" , "foo" , "foo_new" , "new" ) == [
520+ assert await r .hgetex ("test:hash" , keys = [ "foo" , "foo_new" , "new" ] ) == [
501521 b"bar" ,
502522 b"bar1" ,
503523 b"ok" ,
@@ -520,27 +540,27 @@ async def test_hsetex_expiration_exat_and_fxx(r):
520540 "bar1" ,
521541 mapping = {"new" : "ok" },
522542 exat = expire_at ,
523- fxx = True ,
543+ data_persist_option = HashDataPersistOptions . FXX ,
524544 )
525545 == 0
526546 )
527547 ttls = await r .httl ("test:hash" , "foo" , "new" )
528548 assert 10 < ttls [0 ] <= 30
529549 assert ttls [1 ] == - 2
530550
531- assert await r .hgetex ("test:hash" , "foo" , "1" , "new" ) == [b"bar" , b"1" , None ]
551+ assert await r .hgetex ("test:hash" , keys = [ "foo" , "1" , "new" ] ) == [b"bar" , b"1" , None ]
532552 assert (
533553 await r .hsetex (
534554 "test:hash" ,
535555 "foo" ,
536556 "bar1" ,
537557 mapping = {"1" : "new_value" },
538558 exat = expire_at ,
539- fxx = True ,
559+ data_persist_option = HashDataPersistOptions . FXX ,
540560 )
541561 == 1
542562 )
543- assert await r .hgetex ("test:hash" , "foo" , "1" ) == [b"bar1" , b"new_value" ]
563+ assert await r .hgetex ("test:hash" , keys = [ "foo" , "1" ] ) == [b"bar1" , b"new_value" ]
544564
545565
546566@skip_if_server_version_lt ("7.9.0" )
@@ -556,6 +576,3 @@ async def test_hsetex_invalid_inputs(r):
556576
557577 with pytest .raises (exceptions .DataError ):
558578 await r .hsetex ("b" , "foo" , "bar" , ex = 10 , keepttl = True )
559-
560- with pytest .raises (exceptions .DataError ):
561- await r .hsetex ("b" , "foo" , "bar" , ex = 10 , fxx = True , fnx = True )
0 commit comments