@@ -2131,7 +2131,7 @@ async def test_hmset(self, r: valkey.asyncio.Valkey[bytes]):
21312131 )
21322132 h = {b"a" : b"1" , b"b" : b"2" , b"c" : b"3" }
21332133 with pytest .warns (DeprecationWarning , match = warning_message ):
2134- assert await r .hmset ("a" , h ) # type: ignore[arg-type]
2134+ assert await r .hmset ("a" , h ) # type: ignore[arg-type]
21352135 assert await r .hgetall ("a" ) == h
21362136
21372137 async def test_hsetnx (self , r : valkey .asyncio .Valkey [bytes ]):
@@ -2489,6 +2489,248 @@ async def test_geopos_no_value(self, r: valkey.asyncio.Valkey[str]):
24892489 async def test_old_geopos_no_value (self , r : valkey .asyncio .Valkey [str ]):
24902490 assert await r .geopos ("barcelona" , "place1" , "place2" ) == []
24912491
2492+ @skip_if_server_version_lt ("6.2.0" )
2493+ async def test_geosearch (self , r : valkey .Valkey ):
2494+ values = (
2495+ (2.1909389952632 , 41.433791470673 , "place1" )
2496+ + (2.1873744593677 , 41.406342043777 , b"\x80 place2" )
2497+ + (2.583333 , 41.316667 , "place3" )
2498+ )
2499+ await r .geoadd ("barcelona" , values )
2500+ assert await r .geosearch (
2501+ "barcelona" , longitude = 2.191 , latitude = 41.433 , radius = 1000
2502+ ) == [b"place1" ]
2503+ assert await r .geosearch (
2504+ "barcelona" , longitude = 2.187 , latitude = 41.406 , radius = 1000
2505+ ) == [b"\x80 place2" ]
2506+ assert await r .geosearch (
2507+ "barcelona" , longitude = 2.191 , latitude = 41.433 , height = 1000 , width = 1000
2508+ ) == [b"place1" ]
2509+ assert await r .geosearch (
2510+ "barcelona" , member = "place3" , radius = 100 , unit = "km"
2511+ ) == [
2512+ b"\x80 place2" ,
2513+ b"place1" ,
2514+ b"place3" ,
2515+ ]
2516+ # test count
2517+ assert await r .geosearch (
2518+ "barcelona" , member = "place3" , radius = 100 , unit = "km" , count = 2
2519+ ) == [b"place3" , b"\x80 place2" ]
2520+ search_res = await r .geosearch (
2521+ "barcelona" , member = "place3" , radius = 100 , unit = "km" , count = 1 , any = 1
2522+ )
2523+ assert search_res [0 ] in [b"place1" , b"place3" , b"\x80 place2" ]
2524+
2525+ @skip_unless_arch_bits (64 )
2526+ @skip_if_server_version_lt ("6.2.0" )
2527+ async def test_geosearch_member (self , r : valkey .Valkey ):
2528+ values = (2.1909389952632 , 41.433791470673 , "place1" ) + (
2529+ 2.1873744593677 ,
2530+ 41.406342043777 ,
2531+ b"\x80 place2" ,
2532+ )
2533+
2534+ await r .geoadd ("barcelona" , values )
2535+ assert await r .geosearch ("barcelona" , member = "place1" , radius = 10 ) == [b"place1" ]
2536+
2537+ geosearch_place2 , geosearch_place1 = await r .geosearch (
2538+ "barcelona" ,
2539+ member = "place1" ,
2540+ radius = 4000 ,
2541+ withdist = True ,
2542+ withcoord = True ,
2543+ withhash = True ,
2544+ )
2545+
2546+ # All but the coordinates are identical
2547+ assert geosearch_place2 [:- 1 ] == [
2548+ b"\x80 place2" ,
2549+ 3067.4157 ,
2550+ 3471609625421029 ,
2551+ ]
2552+ assert_geo_is_close (
2553+ geosearch_place2 [- 1 ], (2.187376320362091 , 41.40634178640635 )
2554+ )
2555+ assert geosearch_place1 [:- 1 ] == [
2556+ b"place1" ,
2557+ 0.0 ,
2558+ 3471609698139488 ,
2559+ ]
2560+ assert_geo_is_close (
2561+ geosearch_place1 [- 1 ], (2.1909382939338684 , 41.433790281840835 )
2562+ )
2563+
2564+ @skip_if_server_version_lt ("6.2.0" )
2565+ async def test_geosearch_sort (self , r : valkey .Valkey ):
2566+ values = (2.1909389952632 , 41.433791470673 , "place1" ) + (
2567+ 2.1873744593677 ,
2568+ 41.406342043777 ,
2569+ "place2" ,
2570+ )
2571+ await r .geoadd ("barcelona" , values )
2572+ assert await r .geosearch (
2573+ "barcelona" , longitude = 2.191 , latitude = 41.433 , radius = 3000 , sort = "ASC"
2574+ ) == [b"place1" , b"place2" ]
2575+ assert await r .geosearch (
2576+ "barcelona" , longitude = 2.191 , latitude = 41.433 , radius = 3000 , sort = "DESC"
2577+ ) == [b"place2" , b"place1" ]
2578+
2579+ @skip_unless_arch_bits (64 )
2580+ @skip_if_server_version_lt ("6.2.0" )
2581+ @pytest .mark .parametrize (
2582+ "geosearch_kwargs, expected_geosearch_result" ,
2583+ [
2584+ (
2585+ {"withdist" : True , "withcoord" : True , "withhash" : True },
2586+ [b"place1" , 0.0881 , 3471609698139488 ],
2587+ ),
2588+ (
2589+ {"withdist" : True , "withcoord" : True },
2590+ [b"place1" , 0.0881 ],
2591+ ),
2592+ (
2593+ {"withhash" : True , "withcoord" : True },
2594+ [b"place1" , 3471609698139488 ],
2595+ ),
2596+ (
2597+ {"withdist" : True , "withhash" : True },
2598+ [b"place1" , 0.0881 , 3471609698139488 ],
2599+ ),
2600+ ],
2601+ )
2602+ async def test_geosearch_with (
2603+ self ,
2604+ r : valkey .Valkey ,
2605+ geosearch_kwargs : dict [str , Any ],
2606+ expected_geosearch_result : list [Any ],
2607+ ):
2608+ values = (2.1909389952632 , 41.433791470673 , "place1" ) + (
2609+ 2.1873744593677 ,
2610+ 41.406342043777 ,
2611+ "place2" ,
2612+ )
2613+ await r .geoadd ("barcelona" , values )
2614+
2615+ # test a bunch of combinations to test the parse response
2616+ # function.
2617+ geosearch_result = await r .geosearch (
2618+ "barcelona" ,
2619+ longitude = 2.191 ,
2620+ latitude = 41.433 ,
2621+ radius = 1 ,
2622+ unit = "km" ,
2623+ ** geosearch_kwargs ,
2624+ )
2625+ assert len (geosearch_result ) == 1
2626+ if "withcoord" in geosearch_kwargs :
2627+ assert_geo_is_close (
2628+ geosearch_result [0 ][- 1 ], (2.1909382939338684 , 41.433790281840835 )
2629+ )
2630+ assert geosearch_result [0 ][:- 1 ] == expected_geosearch_result
2631+ else :
2632+ assert geosearch_result == [expected_geosearch_result ]
2633+
2634+ assert (
2635+ await r .geosearch (
2636+ "barcelona" ,
2637+ longitude = 2 ,
2638+ latitude = 1 ,
2639+ radius = 1 ,
2640+ unit = "km" ,
2641+ ** geosearch_kwargs ,
2642+ )
2643+ == []
2644+ )
2645+
2646+ @skip_if_server_version_lt ("6.2.0" )
2647+ async def test_geosearch_negative (self , r : valkey .Valkey ):
2648+ # not specifying member nor longitude and latitude
2649+ with pytest .raises (exceptions .DataError ):
2650+ assert await r .geosearch ("barcelona" )
2651+ # specifying member and longitude and latitude
2652+ with pytest .raises (exceptions .DataError ):
2653+ assert await r .geosearch (
2654+ "barcelona" , member = "Paris" , longitude = 2 , latitude = 1
2655+ )
2656+ # specifying one of longitude and latitude
2657+ with pytest .raises (exceptions .DataError ):
2658+ assert await r .geosearch ("barcelona" , longitude = 2 )
2659+ with pytest .raises (exceptions .DataError ):
2660+ assert await r .geosearch ("barcelona" , latitude = 2 )
2661+
2662+ # not specifying radius nor width and height
2663+ with pytest .raises (exceptions .DataError ):
2664+ assert await r .geosearch ("barcelona" , member = "Paris" )
2665+ # specifying radius and width and height
2666+ with pytest .raises (exceptions .DataError ):
2667+ assert await r .geosearch (
2668+ "barcelona" , member = "Paris" , radius = 3 , width = 2 , height = 1
2669+ )
2670+ # specifying one of width and height
2671+ with pytest .raises (exceptions .DataError ):
2672+ assert await r .geosearch ("barcelona" , member = "Paris" , width = 2 )
2673+ with pytest .raises (exceptions .DataError ):
2674+ assert await r .geosearch ("barcelona" , member = "Paris" , height = 2 )
2675+
2676+ # invalid sort
2677+ with pytest .raises (exceptions .DataError ):
2678+ assert await r .geosearch (
2679+ "barcelona" , member = "Paris" , width = 2 , height = 2 , sort = "wrong"
2680+ )
2681+
2682+ # invalid unit
2683+ with pytest .raises (exceptions .DataError ):
2684+ assert await r .geosearch (
2685+ "barcelona" , member = "Paris" , width = 2 , height = 2 , unit = "miles"
2686+ )
2687+
2688+ # use any without count
2689+ with pytest .raises (exceptions .DataError ):
2690+ assert await r .geosearch ("barcelona" , member = "place3" , radius = 100 , any = 1 )
2691+
2692+ @pytest .mark .onlynoncluster
2693+ @skip_if_server_version_lt ("6.2.0" )
2694+ async def test_geosearchstore (self , r : valkey .Valkey ):
2695+ values = (2.1909389952632 , 41.433791470673 , "place1" ) + (
2696+ 2.1873744593677 ,
2697+ 41.406342043777 ,
2698+ "place2" ,
2699+ )
2700+
2701+ await r .geoadd ("barcelona" , values )
2702+ await r .geosearchstore (
2703+ "places_barcelona" ,
2704+ "barcelona" ,
2705+ longitude = 2.191 ,
2706+ latitude = 41.433 ,
2707+ radius = 1000 ,
2708+ )
2709+ assert await r .zrange ("places_barcelona" , 0 , - 1 ) == [b"place1" ]
2710+
2711+ @pytest .mark .onlynoncluster
2712+ @skip_unless_arch_bits (64 )
2713+ @skip_if_server_version_lt ("6.2.0" )
2714+ async def test_geosearchstore_dist (self , r : valkey .Valkey ):
2715+ values = (2.1909389952632 , 41.433791470673 , "place1" ) + (
2716+ 2.1873744593677 ,
2717+ 41.406342043777 ,
2718+ "place2" ,
2719+ )
2720+
2721+ await r .geoadd ("barcelona" , values )
2722+ await r .geosearchstore (
2723+ "places_barcelona" ,
2724+ "barcelona" ,
2725+ longitude = 2.191 ,
2726+ latitude = 41.433 ,
2727+ radius = 1000 ,
2728+ storedist = True ,
2729+ )
2730+ # instead of save the geo score, the distance is saved.
2731+ score = await r .zscore ("places_barcelona" , "place1" )
2732+ assert math .isclose (score , 88.05060698409301 )
2733+
24922734 @skip_if_server_version_lt ("3.2.0" )
24932735 async def test_georadius (self , r : valkey .asyncio .Valkey [str ]):
24942736 values = (2.1909389952632 , 41.433791470673 , "place1" ) + (
0 commit comments