| Index: Tools/Scripts/webkitpy/thirdparty/wpt/wpt/tools/wptserve/wptserve/stash.py
|
| diff --git a/Tools/Scripts/webkitpy/thirdparty/wpt/wpt/tools/wptserve/wptserve/stash.py b/Tools/Scripts/webkitpy/thirdparty/wpt/wpt/tools/wptserve/wptserve/stash.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..39bde3d69268c85fbe48d2340e196a9549c21d83
|
| --- /dev/null
|
| +++ b/Tools/Scripts/webkitpy/thirdparty/wpt/wpt/tools/wptserve/wptserve/stash.py
|
| @@ -0,0 +1,84 @@
|
| +import uuid
|
| +
|
| +#TODO: Consider expiring values after some fixed time for long-running
|
| +#servers
|
| +
|
| +
|
| +class Stash(object):
|
| + """Key-value store for persisting data across HTTP requests.
|
| +
|
| + This data store specifically designed for persisting data across
|
| + HTTP requests. It is entirely in-memory so data will not be
|
| + persisted across server restarts.
|
| +
|
| + This has several unusual properties. Keys are of the form (path,
|
| + uuid), where path is, by default, the path in the HTTP request and
|
| + uuid is a unique id. In addition, the store is write-once, read-once,
|
| + i.e. the value associated with a particular key cannot be changed once
|
| + written and the read operation (called "take") is destructive. Taken together,
|
| + these properties make it difficult for data to accidentally leak
|
| + between different resources or different requests for the same
|
| + resource.
|
| +
|
| + """
|
| +
|
| + data = {}
|
| +
|
| + def __init__(self, default_path):
|
| + self.default_path = default_path
|
| +
|
| + def put(self, key, value, path=None):
|
| + """Place a value in the stash.
|
| +
|
| + :param key: A UUID to use as the data's key.
|
| + :param value: The data to store. This can be any python object.
|
| + :param path: The path that has access to read the data (by default
|
| + the current request path)"""
|
| + if path is None:
|
| + path = self.default_path
|
| + if path not in self.data:
|
| + self.data[path] = PathStash(path)
|
| +
|
| + self.data[path][key] = value
|
| +
|
| + def take(self, key, path=None):
|
| + """Remove a value from the stash and return it.
|
| +
|
| + :param key: A UUID to use as the data's key.
|
| + :param path: The path that has access to read the data (by default
|
| + the current request path)"""
|
| + if path is None:
|
| + path = self.default_path
|
| +
|
| + if path in self.data:
|
| + value = self.data[path][key]
|
| + else:
|
| + value = None
|
| + return value
|
| +
|
| +
|
| +class PathStash(dict):
|
| + def __init__(self, path):
|
| + self.path = path
|
| +
|
| + def __setitem__(self, key, value):
|
| + key = uuid.UUID(key)
|
| + if value is None:
|
| + raise ValueError("Stash value may not be set to None")
|
| + if key in self:
|
| + raise StashError("Tried to overwrite existing stash value "
|
| + "for path %s and key %s (old value was %s, new value is %s)" %
|
| + (self.path, key, self[str(key)], value))
|
| + else:
|
| + dict.__setitem__(self, key, value)
|
| +
|
| + def __getitem__(self, key):
|
| + key = uuid.UUID(key)
|
| + rv = dict.get(self, key, None)
|
| + if rv is not None:
|
| + del self[key]
|
| + return rv
|
| +
|
| +
|
| +class StashError(Exception):
|
| + pass
|
|
|