@@ -1073,7 +1073,7 @@ def hrandfield(self, key, count=None, withvalues=False):
10731073 return self .execute_command ("HRANDFIELD" , key , * params )
10741074
10751075 def randomkey (self ):
1076- "Returns the name of a random key"
1076+ """ Returns the name of a random key"" "
10771077 return self .execute_command ('RANDOMKEY' )
10781078
10791079 def rename (self , src , dst ):
@@ -1083,7 +1083,7 @@ def rename(self, src, dst):
10831083 return self .execute_command ('RENAME' , src , dst )
10841084
10851085 def renamenx (self , src , dst ):
1086- "Rename key ``src`` to ``dst`` if ``dst`` doesn't already exist"
1086+ """ Rename key ``src`` to ``dst`` if ``dst`` doesn't already exist"" "
10871087 return self .execute_command ('RENAMENX' , src , dst )
10881088
10891089 def restore (self , name , ttl , value , replace = False , absttl = False ,
@@ -1545,32 +1545,25 @@ def sort(self, name, start=None, num=None, by=None, get=None,
15451545
15461546 pieces = [name ]
15471547 if by is not None :
1548- pieces .append (b'BY' )
1549- pieces .append (by )
1548+ pieces .extend ([b'BY' , by ])
15501549 if start is not None and num is not None :
1551- pieces .append (b'LIMIT' )
1552- pieces .append (start )
1553- pieces .append (num )
1550+ pieces .extend ([b'LIMIT' , start , num ])
15541551 if get is not None :
15551552 # If get is a string assume we want to get a single value.
15561553 # Otherwise assume it's an interable and we want to get multiple
15571554 # values. We can't just iterate blindly because strings are
15581555 # iterable.
15591556 if isinstance (get , (bytes , str )):
1560- pieces .append (b'GET' )
1561- pieces .append (get )
1557+ pieces .extend ([b'GET' , get ])
15621558 else :
15631559 for g in get :
1564- pieces .append (b'GET' )
1565- pieces .append (g )
1560+ pieces .extend ([b'GET' , g ])
15661561 if desc :
15671562 pieces .append (b'DESC' )
15681563 if alpha :
15691564 pieces .append (b'ALPHA' )
15701565 if store is not None :
1571- pieces .append (b'STORE' )
1572- pieces .append (store )
1573-
1566+ pieces .extend ([b'STORE' , store ])
15741567 if groups :
15751568 if not get or isinstance (get , (bytes , str )) or len (get ) < 2 :
15761569 raise DataError ('when using "groups" the "get" argument '
@@ -1729,15 +1722,15 @@ def zscan_iter(self, name, match=None, count=None,
17291722
17301723 # SET COMMANDS
17311724 def sadd (self , name , * values ):
1732- "Add ``value(s)`` to set ``name``"
1725+ """ Add ``value(s)`` to set ``name``"" "
17331726 return self .execute_command ('SADD' , name , * values )
17341727
17351728 def scard (self , name ):
1736- "Return the number of elements in set ``name``"
1729+ """ Return the number of elements in set ``name``"" "
17371730 return self .execute_command ('SCARD' , name )
17381731
17391732 def sdiff (self , keys , * args ):
1740- "Return the difference of sets specified by ``keys``"
1733+ """ Return the difference of sets specified by ``keys``"" "
17411734 args = list_or_args (keys , args )
17421735 return self .execute_command ('SDIFF' , * args )
17431736
@@ -1750,7 +1743,7 @@ def sdiffstore(self, dest, keys, *args):
17501743 return self .execute_command ('SDIFFSTORE' , dest , * args )
17511744
17521745 def sinter (self , keys , * args ):
1753- "Return the intersection of sets specified by ``keys``"
1746+ """ Return the intersection of sets specified by ``keys``"" "
17541747 args = list_or_args (keys , args )
17551748 return self .execute_command ('SINTER' , * args )
17561749
@@ -1763,15 +1756,17 @@ def sinterstore(self, dest, keys, *args):
17631756 return self .execute_command ('SINTERSTORE' , dest , * args )
17641757
17651758 def sismember (self , name , value ):
1766- "Return a boolean indicating if ``value`` is a member of set ``name``"
1759+ """
1760+ Return a boolean indicating if ``value`` is a member of set ``name``
1761+ """
17671762 return self .execute_command ('SISMEMBER' , name , value )
17681763
17691764 def smembers (self , name ):
1770- "Return all members of the set ``name``"
1765+ """ Return all members of the set ``name``"" "
17711766 return self .execute_command ('SMEMBERS' , name )
17721767
17731768 def smove (self , src , dst , value ):
1774- "Move ``value`` from set ``src`` to set ``dst`` atomically"
1769+ """ Move ``value`` from set ``src`` to set ``dst`` atomically"" "
17751770 return self .execute_command ('SMOVE' , src , dst , value )
17761771
17771772 def spop (self , name , count = None ):
@@ -1850,8 +1845,7 @@ def xadd(self, name, fields, id='*', maxlen=None, approximate=True,
18501845 pieces .append (b'~' )
18511846 pieces .append (minid )
18521847 if limit is not None :
1853- pieces .append (b"LIMIT" )
1854- pieces .append (limit )
1848+ pieces .extend ([b'LIMIT' , limit ])
18551849 if nomkstream :
18561850 pieces .append (b'NOMKSTREAM' )
18571851 pieces .append (id )
@@ -2440,41 +2434,113 @@ def bzpopmin(self, keys, timeout=0):
24402434 keys .append (timeout )
24412435 return self .execute_command ('BZPOPMIN' , * keys )
24422436
2437+ def _zrange (self , command , dest , name , start , end , desc = False ,
2438+ byscore = False , bylex = False , withscores = False ,
2439+ score_cast_func = float , offset = None , num = None ):
2440+ if byscore and bylex :
2441+ raise DataError ("``byscore`` and ``bylex`` can not be "
2442+ "specified together." )
2443+ if (offset is not None and num is None ) or \
2444+ (num is not None and offset is None ):
2445+ raise DataError ("``offset`` and ``num`` must both be specified." )
2446+ if bylex and withscores :
2447+ raise DataError ("``withscores`` not supported in combination "
2448+ "with ``bylex``." )
2449+ pieces = [command ]
2450+ if dest :
2451+ pieces .append (dest )
2452+ pieces .extend ([name , start , end ])
2453+ if byscore :
2454+ pieces .append ('BYSCORE' )
2455+ if bylex :
2456+ pieces .append ('BYLEX' )
2457+ if desc :
2458+ pieces .append ('REV' )
2459+ if offset is not None and num is not None :
2460+ pieces .extend (['LIMIT' , offset , num ])
2461+ if withscores :
2462+ pieces .append ('WITHSCORES' )
2463+ options = {
2464+ 'withscores' : withscores ,
2465+ 'score_cast_func' : score_cast_func
2466+ }
2467+ return self .execute_command (* pieces , ** options )
2468+
24432469 def zrange (self , name , start , end , desc = False , withscores = False ,
2444- score_cast_func = float ):
2470+ score_cast_func = float , byscore = False , bylex = False ,
2471+ offset = None , num = None ):
24452472 """
24462473 Return a range of values from sorted set ``name`` between
24472474 ``start`` and ``end`` sorted in ascending order.
24482475
24492476 ``start`` and ``end`` can be negative, indicating the end of the range.
24502477
2451- ``desc`` a boolean indicating whether to sort the results descendingly
2478+ ``desc`` a boolean indicating whether to sort the results in reversed
2479+ order.
24522480
24532481 ``withscores`` indicates to return the scores along with the values.
2482+ The return type is a list of (value, score) pairs.
2483+
2484+ ``score_cast_func`` a callable used to cast the score return value.
2485+
2486+ ``byscore`` when set to True, returns the range of elements from the
2487+ sorted set having scores equal or between ``start`` and ``end``.
2488+
2489+ ``bylex`` when set to True, returns the range of elements from the
2490+ sorted set between the ``start`` and ``end`` lexicographical closed
2491+ range intervals.
2492+ Valid ``start`` and ``end`` must start with ( or [, in order to specify
2493+ whether the range interval is exclusive or inclusive, respectively.
2494+
2495+ ``offset`` and ``num`` are specified, then return a slice of the range.
2496+ Can't be provided when using ``bylex``.
2497+ """
2498+ return self ._zrange ('ZRANGE' , None , name , start , end , desc , byscore ,
2499+ bylex , withscores , score_cast_func , offset , num )
2500+
2501+ def zrevrange (self , name , start , end , withscores = False ,
2502+ score_cast_func = float ):
2503+ """
2504+ Return a range of values from sorted set ``name`` between
2505+ ``start`` and ``end`` sorted in descending order.
2506+
2507+ ``start`` and ``end`` can be negative, indicating the end of the range.
2508+
2509+ ``withscores`` indicates to return the scores along with the values
24542510 The return type is a list of (value, score) pairs
24552511
24562512 ``score_cast_func`` a callable used to cast the score return value
24572513 """
2458- if desc :
2459- return self .zrevrange (name , start , end , withscores ,
2460- score_cast_func )
2461- pieces = ['ZRANGE' , name , start , end ]
2462- if withscores :
2463- pieces .append (b'WITHSCORES' )
2464- options = {
2465- 'withscores' : withscores ,
2466- 'score_cast_func' : score_cast_func
2467- }
2468- return self .execute_command (* pieces , ** options )
2514+ return self .zrange (name , start , end , desc = True ,
2515+ withscores = withscores ,
2516+ score_cast_func = score_cast_func )
24692517
2470- def zrangestore (self , dest , name , start , end ):
2518+ def zrangestore (self , dest , name , start , end ,
2519+ byscore = False , bylex = False , desc = False ,
2520+ offset = None , num = None ):
24712521 """
24722522 Stores in ``dest`` the result of a range of values from sorted set
24732523 ``name`` between ``start`` and ``end`` sorted in ascending order.
24742524
24752525 ``start`` and ``end`` can be negative, indicating the end of the range.
2526+
2527+ ``byscore`` when set to True, returns the range of elements from the
2528+ sorted set having scores equal or between ``start`` and ``end``.
2529+
2530+ ``bylex`` when set to True, returns the range of elements from the
2531+ sorted set between the ``start`` and ``end`` lexicographical closed
2532+ range intervals.
2533+ Valid ``start`` and ``end`` must start with ( or [, in order to specify
2534+ whether the range interval is exclusive or inclusive, respectively.
2535+
2536+ ``desc`` a boolean indicating whether to sort the results in reversed
2537+ order.
2538+
2539+ ``offset`` and ``num`` are specified, then return a slice of the range.
2540+ Can't be provided when using ``bylex``.
24762541 """
2477- return self .execute_command ('ZRANGESTORE' , dest , name , start , end )
2542+ return self ._zrange ('ZRANGESTORE' , dest , name , start , end , desc ,
2543+ byscore , bylex , False , None , offset , num )
24782544
24792545 def zrangebylex (self , name , min , max , start = None , num = None ):
24802546 """
@@ -2484,13 +2550,7 @@ def zrangebylex(self, name, min, max, start=None, num=None):
24842550 If ``start`` and ``num`` are specified, then return a slice of the
24852551 range.
24862552 """
2487- if (start is not None and num is None ) or \
2488- (num is not None and start is None ):
2489- raise DataError ("``start`` and ``num`` must both be specified" )
2490- pieces = ['ZRANGEBYLEX' , name , min , max ]
2491- if start is not None and num is not None :
2492- pieces .extend ([b'LIMIT' , start , num ])
2493- return self .execute_command (* pieces )
2553+ return self .zrange (name , min , max , bylex = True , offset = start , num = num )
24942554
24952555 def zrevrangebylex (self , name , max , min , start = None , num = None ):
24962556 """
@@ -2500,13 +2560,8 @@ def zrevrangebylex(self, name, max, min, start=None, num=None):
25002560 If ``start`` and ``num`` are specified, then return a slice of the
25012561 range.
25022562 """
2503- if (start is not None and num is None ) or \
2504- (num is not None and start is None ):
2505- raise DataError ("``start`` and ``num`` must both be specified" )
2506- pieces = ['ZREVRANGEBYLEX' , name , max , min ]
2507- if start is not None and num is not None :
2508- pieces .extend ([b'LIMIT' , start , num ])
2509- return self .execute_command (* pieces )
2563+ return self .zrange (name , max , min , desc = True ,
2564+ bylex = True , offset = start , num = num )
25102565
25112566 def zrangebyscore (self , name , min , max , start = None , num = None ,
25122567 withscores = False , score_cast_func = float ):
@@ -2522,19 +2577,29 @@ def zrangebyscore(self, name, min, max, start=None, num=None,
25222577
25232578 `score_cast_func`` a callable used to cast the score return value
25242579 """
2525- if (start is not None and num is None ) or \
2526- (num is not None and start is None ):
2527- raise DataError ("``start`` and ``num`` must both be specified" )
2528- pieces = ['ZRANGEBYSCORE' , name , min , max ]
2529- if start is not None and num is not None :
2530- pieces .extend ([b'LIMIT' , start , num ])
2531- if withscores :
2532- pieces .append (b'WITHSCORES' )
2533- options = {
2534- 'withscores' : withscores ,
2535- 'score_cast_func' : score_cast_func
2536- }
2537- return self .execute_command (* pieces , ** options )
2580+ return self .zrange (name , min , max , byscore = True ,
2581+ offset = start , num = num ,
2582+ withscores = withscores ,
2583+ score_cast_func = score_cast_func )
2584+
2585+ def zrevrangebyscore (self , name , max , min , start = None , num = None ,
2586+ withscores = False , score_cast_func = float ):
2587+ """
2588+ Return a range of values from the sorted set ``name`` with scores
2589+ between ``min`` and ``max`` in descending order.
2590+
2591+ If ``start`` and ``num`` are specified, then return a slice
2592+ of the range.
2593+
2594+ ``withscores`` indicates to return the scores along with the values.
2595+ The return type is a list of (value, score) pairs
2596+
2597+ ``score_cast_func`` a callable used to cast the score return value
2598+ """
2599+ return self .zrange (name , max , min , desc = True ,
2600+ byscore = True , offset = start ,
2601+ num = num , withscores = withscores ,
2602+ score_cast_func = score_cast_func )
25382603
25392604 def zrank (self , name , value ):
25402605 """
@@ -2572,56 +2637,6 @@ def zremrangebyscore(self, name, min, max):
25722637 """
25732638 return self .execute_command ('ZREMRANGEBYSCORE' , name , min , max )
25742639
2575- def zrevrange (self , name , start , end , withscores = False ,
2576- score_cast_func = float ):
2577- """
2578- Return a range of values from sorted set ``name`` between
2579- ``start`` and ``end`` sorted in descending order.
2580-
2581- ``start`` and ``end`` can be negative, indicating the end of the range.
2582-
2583- ``withscores`` indicates to return the scores along with the values
2584- The return type is a list of (value, score) pairs
2585-
2586- ``score_cast_func`` a callable used to cast the score return value
2587- """
2588- pieces = ['ZREVRANGE' , name , start , end ]
2589- if withscores :
2590- pieces .append (b'WITHSCORES' )
2591- options = {
2592- 'withscores' : withscores ,
2593- 'score_cast_func' : score_cast_func
2594- }
2595- return self .execute_command (* pieces , ** options )
2596-
2597- def zrevrangebyscore (self , name , max , min , start = None , num = None ,
2598- withscores = False , score_cast_func = float ):
2599- """
2600- Return a range of values from the sorted set ``name`` with scores
2601- between ``min`` and ``max`` in descending order.
2602-
2603- If ``start`` and ``num`` are specified, then return a slice
2604- of the range.
2605-
2606- ``withscores`` indicates to return the scores along with the values.
2607- The return type is a list of (value, score) pairs
2608-
2609- ``score_cast_func`` a callable used to cast the score return value
2610- """
2611- if (start is not None and num is None ) or \
2612- (num is not None and start is None ):
2613- raise DataError ("``start`` and ``num`` must both be specified" )
2614- pieces = ['ZREVRANGEBYSCORE' , name , max , min ]
2615- if start is not None and num is not None :
2616- pieces .extend ([b'LIMIT' , start , num ])
2617- if withscores :
2618- pieces .append (b'WITHSCORES' )
2619- options = {
2620- 'withscores' : withscores ,
2621- 'score_cast_func' : score_cast_func
2622- }
2623- return self .execute_command (* pieces , ** options )
2624-
26252640 def zrevrank (self , name , value ):
26262641 """
26272642 Returns a 0-based value indicating the descending rank of
0 commit comments