@@ -530,15 +530,15 @@ def parse_client_info(value):
530530 "key1=value1 key2=value2 key3=value3"
531531 """
532532 client_info = {}
533- infos = value .split (" " )
533+ infos = str_if_bytes ( value ) .split (" " )
534534 for info in infos :
535535 key , value = info .split ("=" )
536536 client_info [key ] = value
537537
538538 # Those fields are definded as int in networking.c
539539 for int_key in {"id" , "age" , "idle" , "db" , "sub" , "psub" ,
540540 "multi" , "qbuf" , "qbuf-free" , "obl" ,
541- "oll" , "omem" }:
541+ "argv-mem" , " oll" , "omem" , "tot-mem " }:
542542 client_info [int_key ] = int (client_info [int_key ])
543543 return client_info
544544
@@ -620,6 +620,7 @@ class Redis:
620620 'CLIENT ID' : int ,
621621 'CLIENT KILL' : parse_client_kill ,
622622 'CLIENT LIST' : parse_client_list ,
623+ 'CLIENT INFO' : parse_client_info ,
623624 'CLIENT SETNAME' : bool_ok ,
624625 'CLIENT UNBLOCK' : lambda r : r and int (r ) == 1 or False ,
625626 'CLIENT PAUSE' : bool_ok ,
@@ -1243,6 +1244,13 @@ def client_kill_filter(self, _id=None, _type=None, addr=None, skipme=None):
12431244 "<value> must specify at least one filter" )
12441245 return self .execute_command ('CLIENT KILL' , * args )
12451246
1247+ def client_info (self ):
1248+ """
1249+ Returns information and statistics about the current
1250+ client connection.
1251+ """
1252+ return self .execute_command ('CLIENT INFO' )
1253+
12461254 def client_list (self , _type = None ):
12471255 """
12481256 Returns a list of currently connected clients.
@@ -1689,6 +1697,7 @@ def get(self, name):
16891697 """
16901698 return self .execute_command ('GET' , name )
16911699
1700+
16921701 def getdel (self , name ):
16931702 """
16941703 Get the value at key ``name`` and delete the key. This command
@@ -1698,6 +1707,57 @@ def getdel(self, name):
16981707 """
16991708 return self .execute_command ('GETDEL' , name )
17001709
1710+ def getex (self , name ,
1711+ ex = None , px = None , exat = None , pxat = None , persist = False ):
1712+ """
1713+ Get the value of key and optionally set its expiration.
1714+ GETEX is similar to GET, but is a write command with
1715+ additional options. All time parameters can be given as
1716+ datetime.timedelta or integers.
1717+
1718+ ``ex`` sets an expire flag on key ``name`` for ``ex`` seconds.
1719+
1720+ ``px`` sets an expire flag on key ``name`` for ``px`` milliseconds.
1721+
1722+ ``exat`` sets an expire flag on key ``name`` for ``ex`` seconds,
1723+ specified in unix time.
1724+
1725+ ``pxat`` sets an expire flag on key ``name`` for ``ex`` milliseconds,
1726+ specified in unix time.
1727+
1728+ ``persist`` remove the time to live associated with ``name``.
1729+ """
1730+
1731+ pieces = []
1732+ # similar to set command
1733+ if ex is not None :
1734+ pieces .append ('EX' )
1735+ if isinstance (ex , datetime .timedelta ):
1736+ ex = int (ex .total_seconds ())
1737+ pieces .append (ex )
1738+ if px is not None :
1739+ pieces .append ('PX' )
1740+ if isinstance (px , datetime .timedelta ):
1741+ px = int (px .total_seconds () * 1000 )
1742+ pieces .append (px )
1743+ # similar to pexpireat command
1744+ if exat is not None :
1745+ pieces .append ('EXAT' )
1746+ if isinstance (exat , datetime .datetime ):
1747+ s = int (exat .microsecond / 1000000 )
1748+ exat = int (mod_time .mktime (exat .timetuple ())) + s
1749+ pieces .append (exat )
1750+ if pxat is not None :
1751+ pieces .append ('PXAT' )
1752+ if isinstance (pxat , datetime .datetime ):
1753+ ms = int (pxat .microsecond / 1000 )
1754+ pxat = int (mod_time .mktime (pxat .timetuple ())) * 1000 + ms
1755+ pieces .append (pxat )
1756+ if persist :
1757+ pieces .append ('PERSIST' )
1758+
1759+ return self .execute_command ('GETEX' , name , * pieces )
1760+
17011761 def __getitem__ (self , name ):
17021762 """
17031763 Return the value at key ``name``, raises a KeyError if the key
@@ -1829,6 +1889,26 @@ def pttl(self, name):
18291889 "Returns the number of milliseconds until the key ``name`` will expire"
18301890 return self .execute_command ('PTTL' , name )
18311891
1892+ def hrandfield (self , key , count = None , withvalues = False ):
1893+ """
1894+ Return a random field from the hash value stored at key.
1895+
1896+ count: if the argument is positive, return an array of distinct fields.
1897+ If called with a negative count, the behavior changes and the command
1898+ is allowed to return the same field multiple times. In this case,
1899+ the number of returned fields is the absolute value of the
1900+ specified count.
1901+ withvalues: The optional WITHVALUES modifier changes the reply so it
1902+ includes the respective values of the randomly selected hash fields.
1903+ """
1904+ params = []
1905+ if count is not None :
1906+ params .append (count )
1907+ if withvalues :
1908+ params .append ("WITHVALUES" )
1909+
1910+ return self .execute_command ("HRANDFIELD" , key , * params )
1911+
18321912 def randomkey (self ):
18331913 "Returns the name of a random key"
18341914 return self .execute_command ('RANDOMKEY' )
0 commit comments