@@ -530,15 +530,15 @@ def parse_client_info(value):
530
530
"key1=value1 key2=value2 key3=value3"
531
531
"""
532
532
client_info = {}
533
- infos = value .split (" " )
533
+ infos = str_if_bytes ( value ) .split (" " )
534
534
for info in infos :
535
535
key , value = info .split ("=" )
536
536
client_info [key ] = value
537
537
538
538
# Those fields are definded as int in networking.c
539
539
for int_key in {"id" , "age" , "idle" , "db" , "sub" , "psub" ,
540
540
"multi" , "qbuf" , "qbuf-free" , "obl" ,
541
- "oll" , "omem" }:
541
+ "argv-mem" , " oll" , "omem" , "tot-mem " }:
542
542
client_info [int_key ] = int (client_info [int_key ])
543
543
return client_info
544
544
@@ -620,6 +620,7 @@ class Redis:
620
620
'CLIENT ID' : int ,
621
621
'CLIENT KILL' : parse_client_kill ,
622
622
'CLIENT LIST' : parse_client_list ,
623
+ 'CLIENT INFO' : parse_client_info ,
623
624
'CLIENT SETNAME' : bool_ok ,
624
625
'CLIENT UNBLOCK' : lambda r : r and int (r ) == 1 or False ,
625
626
'CLIENT PAUSE' : bool_ok ,
@@ -1243,6 +1244,13 @@ def client_kill_filter(self, _id=None, _type=None, addr=None, skipme=None):
1243
1244
"<value> must specify at least one filter" )
1244
1245
return self .execute_command ('CLIENT KILL' , * args )
1245
1246
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
+
1246
1254
def client_list (self , _type = None ):
1247
1255
"""
1248
1256
Returns a list of currently connected clients.
@@ -1689,6 +1697,7 @@ def get(self, name):
1689
1697
"""
1690
1698
return self .execute_command ('GET' , name )
1691
1699
1700
+
1692
1701
def getdel (self , name ):
1693
1702
"""
1694
1703
Get the value at key ``name`` and delete the key. This command
@@ -1698,6 +1707,57 @@ def getdel(self, name):
1698
1707
"""
1699
1708
return self .execute_command ('GETDEL' , name )
1700
1709
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
+
1701
1761
def __getitem__ (self , name ):
1702
1762
"""
1703
1763
Return the value at key ``name``, raises a KeyError if the key
@@ -1829,6 +1889,26 @@ def pttl(self, name):
1829
1889
"Returns the number of milliseconds until the key ``name`` will expire"
1830
1890
return self .execute_command ('PTTL' , name )
1831
1891
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
+
1832
1912
def randomkey (self ):
1833
1913
"Returns the name of a random key"
1834
1914
return self .execute_command ('RANDOMKEY' )
0 commit comments