def set(self, appid, userid, key, value, if_match=None): """Set the value stored under the specified key.""" qargs = {"key": key, "value": value} set_query = "UPDATE items SET value = :value"\ " WHERE bucket = :bucket AND key = :key" ins_query = "INSERT INTO items VALUES (:bucket, :key, :value)" # We need a transaction in order to check the etag. connection = self._engine.connect() trn = connection.begin() try: try: item = self.getitem(appid, userid, key, connection) except KeyError: if if_match is not None: if if_match != "": raise ConflictError(key) qargs["bucket"] = self._getbucket(appid, userid) connection.execute(ins_query, **qargs) else: if if_match is not None: if item.etag != if_match: raise ConflictError(key) qargs["bucket"] = item.bucket connection.execute(set_query, **qargs) trn.commit() etag = md5(value).hexdigest() return Item(appid, userid, key, value, etag) except: trn.rollback() raise finally: connection.close()
def set(self, key, value, userid=None, appid=None, if_match=None): """Set the value stored under the specified key.""" path = self.keypath(key, userid, appid) headers = {} if if_match is not None: if if_match == "": headers["If-None-Match"] = "*" else: headers["If-Match"] = if_match r = self.request(path, "PUT", dict(value=value), headers) return Item(appid, userid, key, value, r.headers.get("ETag"))
def getitem(self, appid, userid, key, connection=None): """Get the item stored under the specified key.""" if connection is None: connection = self query = "SELECT i.value, k.bucket FROM items i, buckets k"\ " WHERE i.bucket = k.bucket"\ " AND k.appid = :appid AND k.userid = :userid"\ " AND key = :key" qargs = {"appid": appid, "userid": userid, "key": key} row = connection.execute(query, **qargs).fetchone() if row is None: raise KeyError(key) etag = md5(row[0]).hexdigest() item = Item(appid, userid, key, row[0], etag) item.bucket = row[1] if isinstance(item.key, unicode): item.key = item.key.encode("utf8") if isinstance(item.value, unicode): item.value = item.value.encode("utf8") return item
class WebAPISession(object): """ISauropodSession implemented by calling the HTTP-based API.""" implements(ISauropodSession) def __init__(self, store, userid, sessionid): self.store = store self.userid = userid self.sessionid = sessionid def close(self): """Close down the session.""" pass def request(self, path="", method="GET", data="", headers=None): """Make a HTTP request to the Sauropod server, return the result. This method is a handy wrapper around the Store.request method, to make sure that it uses the correct session for OAuth signing. """ return self.store.request(path, method, data, headers, self) def keypath(self, key, userid=None, appid=None): """Get the server path at which to access the given key.""" if userid is None: userid = self.userid if appid is None: appid = self.store.appid path = "/app/%s/users/%s/keys/%s" path = path % tuple(urlquote(v, safe="") for v in (appid, userid, key)) return path def getitem(self, key, userid=None, appid=None): """Get the item stored under the specified key.""" path = self.keypath(key, userid, appid) try: r = self.request(path, "GET") except ServerError, e: if e.status_code == 404: raise KeyError(key) raise value = json.loads(r.content)["value"] return Item(appid, userid, key, value, r.headers.get("ETag"))