Commits

Reid Draper committed d0c72eb

add exists, delete, and auth

Comments (0)

Files changed (2)

         result.extend(item)
     return result
 
+def _reallylist(value):
+    if isinstance(value, (list, tuple)):
+        return value
+    else:
+        return [value]
+
 class RedisTornado(object):
     def __init__(self, host = None, port = None, encoding = 'utf-8'):
         """
                 result.append(response)
                 num_remaining-= 1
             callback(result)
+            self.waiting = False
+            self._work()
+            return
         
         elif response[0] == '$':
             # bulk reply
             
         elif response[0] == '+':
             # single line reply
-            callback(True)
+            text = response[1:-2]
+            if text == 'OK':
+                callback(True)
+            else:
+                callback(text)
             self._waiting = False
             self._work()
             return
             self._work()
             return
 
+        elif response[0] == ':':
+            # integer reply
+            callback(int(response[1:-2]))
+            self._waiting = False
+            self._work()
+            return
+
     def _encode(self, value):
         if isinstance(value, unicode):
             return value.encode(self.encoding)
         args_string = ''.join('$%d\r\n%s\r\n' % (len(arg), arg) for arg in args)
         cmd = '*%d\r\n$%d\r\n%s\r\n%s' % (num_args, len(command), command, args_string)
         return cmd
-        
-    def set(self, key, value, callback = None):
-        cmd = self._cmd_creator('SET', [key, value])
-        self._queue.append((cmd, callback))
-        if not self._waiting:
-            self._work()
-        
-    def mset(self, kv_list, callback = None):
-        cmd = self._cmd_creator('MSET', _flatten(kv_list))
+
+    def _go(self, cmd, callback):
         self._queue.append((cmd, callback))
         if not self._waiting:
             self._work()
 
+    # begin commands from http://code.google.com/p/redis/wiki/CommandReference
+    # they appear in the same order as the page above
+
+    # connection handling
+    def quit(self, callback = None):
+        pass
+        #cmd = '*1\r\n$4\r\nQUIT\r\n'
+        #self._go(cmd, callback)
+        # TODO
+        # don't let further requests in, without reconnecting
+
+    def auth(self, password, callback = None):
+        cmd = self._cmd_creator('AUTH', [password])
+        self._go(cmd, callback)
+
+    # Commands operating on all value types
+    @swirl.asynchronous
+    def exists(self, key, callback = None):
+        value = yield lambda cb: self._exists(key, cb)
+        if callback:
+            callback(bool(value))
+
+    def _exists(self, key, callback):
+        cmd = self._cmd_creator('EXISTS', [key])
+        self._go(cmd, callback)
+
+    def delete(self, keys, callback = None):
+        keys = _reallylist(keys)
+        cmd = self._cmd_creator('DEL', keys)
+        self._go(cmd, callback)
+
+    def type(self, key, callback = None):
+        cmd = self._cmd_creator('TYPE', [key])
+        self._go(cmd, callback)
+
+    def keys(self, pattern, callback = None):
+        cmd = self._cmd_creator('KEYS', [pattern])
+        self._go(cmd, callback)
+
+    def randomkey(self, callback = None):
+        cmd = self._cmd_creator('RANDOMKEY', [pattern])
+        self._go(cmd, callback)
+
+    def rename(self, oldkey, newkey, callback = None):
+        cmd = self._cmd_creator('RENAME', [oldkey, newkey])
+        self._go(cmd, callback)
+
+    @swirl.asynchronous
+    def renamenx(self, oldkey, newkey, callback = None):
+        value = yield lambda cb: self._renamenx(key, cb)
+        if callback:
+            callback(bool(value))
+
+    def _renamenx(self, oldkey, newkey, callback = None):
+        cmd = self._cmd_creator('RENAMENX', [oldkey, newkey])
+        self._go(cmd, callback)
+
+    def dbsize(self, callback = None):
+        cmd = self._cmd_creator('DBSIZE', [])
+        self._go(cmd, callback)
+
+    @swirl.asynchronous
+    def expire(self, key, seconds, callback = None):
+        value = yield lambda cb: self._expire(key, seconds, cb)
+        if callback:
+            callback(bool(value))
+
+    def _expire(self, key, seconds, callback = None):
+        cmd = self._cmd_creator('EXPIRE', [key, seconds])
+        self._go(cmd, callback)
+
+    @swirl.asynchronous
+    def expireat(self, key, unix_time, callback = None):
+        value = yield lambda cb: self._expireat(key, unix_time, cb)
+        if callback:
+            callback(bool(value))
+
+    def _expireat(self, key, unix_time, callback = None):
+        cmd = self._cmd_creator('EXPIREAT', [key, seconds])
+        self._go(cmd, callback)
+
+# -------------------------------------------------------
+        
+    def set(self, key, value, callback = None):
+        cmd = self._cmd_creator('SET', [key, value])
+        self._go(cmd, callback)
+        
+    def mset(self, kv_list, callback = None):
+        cmd = self._cmd_creator('MSET', _flatten(kv_list))
+        self._go(cmd, callback)
+
     def get(self, key, callback = None):
         cmd = self._cmd_creator('GET', [key])
-        self._queue.append((cmd, callback))
-        if not self._waiting:
-            self._work()
+        self._go(cmd, callback)
 
     def mget(self, keys, callback = None):
         cmd = self._cmd_creator('MGET', keys)
-        self._queue.append((cmd, callback))
-        if not self._waiting:
-            self._work()
+        self._go(cmd, callback)
 
 r = RedisTornado()
 
+# begin commands from http://code.google.com/p/redis/wiki/CommandReference
+# they appear in the same order as the page above
+
+# connection handling
+
+class QuitHandler(tornado.web.RequestHandler):
+    @swirl.asynchronous
+    def post(self):
+        pass
+        #yield lambda cb : r.quit(cb)
+
+class AuthHandler(tornado.web.RequestHandler):
+    @swirl.asynchronous
+    def post(self):
+        password = self.get_argument('password')
+        response = yield lambda cb: r.auth(password, cb)
+        self.write(str(response))
+
+# Commands operating on all value types
+class ExistsHandler(tornado.web.RequestHandler):
+    @swirl.asynchronous
+    def get(self, key):
+        response = yield lambda cb: r.exists(key, cb)
+        self.write(str(response))
+
+class DeleteHandler(tornado.web.RequestHandler):
+    @swirl.asynchronous
+    def post(self):
+        keys = self.get_arguments('key')
+        response = yield lambda cb: r.delete(keys, cb)
+        self.write(str(response))
+
+# ---------------------------------------------
 class GetHandler(tornado.web.RequestHandler):
     @swirl.asynchronous
     def get(self, key):
 def main():
     tornado.options.parse_command_line()
     application = tornado.web.Application([
+        # connection handling
+        (r'/quit/*',        QuitHandler),
+        (r'/auth',          AuthHandler),
+        # Commands operating on all value types
+        (r'/exists/(.+)',   ExistsHandler),
+        (r'/delete',        DeleteHandler),
+
+        # -------------------------------
         (r'/get/(.+)',      GetHandler),
         (r'/set/(.+)',      SetHandler),
         (r'/mset/*',        MSetHandler),
-        (r'/mget',        MGetHandler),
+        (r'/mget',          MGetHandler),
     ], **settings)
     http_server = tornado.httpserver.HTTPServer(application)
     http_server.listen(options.port)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.