{"action":"created","comment":{"url":"https://api.github.com/repos/mitsuhiko/werkzeug/pulls/comments/36341177","id":36341177,"diff_hunk":"@@ -793,3 +794,64 @@ def has(self, key):\n                     return False\n         except (IOError, OSError, pickle.PickleError):\n             return False\n+\n+\n+class UWSGICache(BaseCache):\n+    \"\"\" Implements the cache using uWSGI's caching framework.\n+\n+    .. note::\n+        This class cannot be used when running under PyPy, because the uWSGI\n+        API implementation for PyPy is lacking the needed functionality.\n+\n+    :param default_timeout: The default timeout in seconds.\n+    :param cache: The name of the caching instance to connect to, for\n+        example: mycache@localhost:3031, defaults to an empty string, which\n+        means uWSGI will cache in the local instance. If the cache is in the\n+        same instance as the werkzeug app, you only have to provide the name of\n+        the cache.\n+    \"\"\"\n+    def __init__(self, default_timeout=300, cache=''):\n+        BaseCache.__init__(self, default_timeout)\n+\n+        if platform.python_implementation() == 'PyPy':\n+            raise RuntimeError(\"uWSGI caching does not work under PyPy, see \"\n+                               \"the docs for more details.\")\n+\n+        try:\n+            import uwsgi\n+            self._uwsgi = uwsgi\n+        except ImportError:\n+            raise RuntimeError(\"uWSGI could not be imported, are you \"\n+                               \"running under uWSGI?\")\n+\n+        self.cache = cache\n+\n+    def _get_expiration(self, timeout):\n+        if timeout is None:\n+            timeout = self.default_timeout\n+        return timeout\n+\n+    def get(self, key):\n+        rv = self._uwsgi.cache_get(key, self.cache)\n+        if rv is None:\n+            return\n+        return pickle.loads(rv)\n+\n+    def delete(self, key):\n+        return self._uwsgi.cache_del(key, self.cache)\n+\n+    def set(self, key, value, timeout=None):\n+        return self._uwsgi.cache_update(key, pickle.dumps(value),\n+                                        self._get_expiration(timeout),\n+                                        self.cache)\n+\n+    def add(self, key, value, timeout=None):","path":"werkzeug/contrib/cache.py","position":72,"original_position":72,"commit_id":"1fdc31d54737a72148cfdef701f352eadc2f0ff4","original_commit_id":"1fdc31d54737a72148cfdef701f352eadc2f0ff4","user":{"login":"untitaker","id":837573,"avatar_url":"https://avatars.githubusercontent.com/u/837573?v=3","gravatar_id":"","url":"https://api.github.com/users/untitaker","html_url":"https://github.com/untitaker","followers_url":"https://api.github.com/users/untitaker/followers","following_url":"https://api.github.com/users/untitaker/following{/other_user}","gists_url":"https://api.github.com/users/untitaker/gists{/gist_id}","starred_url":"https://api.github.com/users/untitaker/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/untitaker/subscriptions","organizations_url":"https://api.github.com/users/untitaker/orgs","repos_url":"https://api.github.com/users/untitaker/repos","events_url":"https://api.github.com/users/untitaker/events{/privacy}","received_events_url":"https://api.github.com/users/untitaker/received_events","type":"User","site_admin":false},"body":"While the docs don't mention it, I think atomic behavior is strongly preferred, is this possible?","created_at":"2015-08-05T19:05:30Z","updated_at":"2015-08-05T19:05:30Z","html_url":"https://github.com/mitsuhiko/werkzeug/pull/736#discussion_r36341177","pull_request_url":"https://api.github.com/repos/mitsuhiko/werkzeug/pulls/736","_links":{"self":{"href":"https://api.github.com/repos/mitsuhiko/werkzeug/pulls/comments/36341177"},"html":{"href":"https://github.com/mitsuhiko/werkzeug/pull/736#discussion_r36341177"},"pull_request":{"href":"https://api.github.com/repos/mitsuhiko/werkzeug/pulls/736"}}},"pull_request":{"url":"https://api.github.com/repos/mitsuhiko/werkzeug/pulls/736","id":36145890,"html_url":"https://github.com/mitsuhiko/werkzeug/pull/736","diff_url":"https://github.com/mitsuhiko/werkzeug/pull/736.diff","patch_url":"https://github.com/mitsuhiko/werkzeug/pull/736.patch","issue_url":"https://api.github.com/repos/mitsuhiko/werkzeug/issues/736","number":736,"state":"open","locked":false,"title":"Add uWSGI caching backend","user":{"login":"jaapz","id":513050,"avatar_url":"https://avatars.githubusercontent.com/u/513050?v=3","gravatar_id":"","url":"https://api.github.com/users/jaapz","html_url":"https://github.com/jaapz","followers_url":"https://api.github.com/users/jaapz/followers","following_url":"https://api.github.com/users/jaapz/following{/other_user}","gists_url":"https://api.github.com/users/jaapz/gists{/gist_id}","starred_url":"https://api.github.com/users/jaapz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jaapz/subscriptions","organizations_url":"https://api.github.com/users/jaapz/orgs","repos_url":"https://api.github.com/users/jaapz/repos","events_url":"https://api.github.com/users/jaapz/events{/privacy}","received_events_url":"https://api.github.com/users/jaapz/received_events","type":"User","site_admin":false},"body":"Since version 1.9 uWSGI includes an in-memory cache. Documentation on that can be found at the [uWSGI docs][1].\r\n\r\nThis PR contains a new UwsgiCache class using uWSGI's `uwsgi.cache_*` functions.\r\n\r\nI'm not sure yet about a few things:\r\n\r\n1) testing; as `import uwsgi` only works when the app is actually run by uwsgi, writing tests with the actual uwsgi module is basically impossible to my knowledge. Does anyone have an idea on how this could be done?\r\n\r\n2) uWSGI also has `cache_inc` and `cache_dec` functions since 1.9.9, but they are not documented, so I'm a bit hesitant on adding them.\r\n\r\n3) Naming; is the convention here to use `uWSGICache`, or `UwsgiCache`?\r\n\r\n4) Documentation; because I check for the existance of the uwsgi module and only define the actual UwsgiCache class when it exists, sphinx's `automodule` does not pick up on the \"real\" UwsgiCache class. What's the best way of handling this?\r\n\r\n[1]: http://uwsgi-docs.readthedocs.org/en/latest/Caching.html","created_at":"2015-05-25T15:29:21Z","updated_at":"2015-08-05T19:05:30Z","closed_at":null,"merged_at":null,"merge_commit_sha":"6a96ccfdd833c72f331ec30b6ff1b5c5ab0e6a11","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/mitsuhiko/werkzeug/pulls/736/commits","review_comments_url":"https://api.github.com/repos/mitsuhiko/werkzeug/pulls/736/comments","review_comment_url":"https://api.github.com/repos/mitsuhiko/werkzeug/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mitsuhiko/werkzeug/issues/736/comments","statuses_url":"https://api.github.com/repos/mitsuhiko/werkzeug/statuses/1fdc31d54737a72148cfdef701f352eadc2f0ff4","head":{"label":"jaapz:master","ref":"master","sha":"1fdc31d54737a72148cfdef701f352eadc2f0ff4","user":{"login":"jaapz","id":513050,"avatar_url":"https://avatars.githubusercontent.com/u/513050?v=3","gravatar_id":"","url":"https://api.github.com/users/jaapz","html_url":"https://github.com/jaapz","followers_url":"https://api.github.com/users/jaapz/followers","following_url":"https://api.github.com/users/jaapz/following{/other_user}","gists_url":"https://api.github.com/users/jaapz/gists{/gist_id}","starred_url":"https://api.github.com/users/jaapz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jaapz/subscriptions","organizations_url":"https://api.github.com/users/jaapz/orgs","repos_url":"https://api.github.com/users/jaapz/repos","events_url":"https://api.github.com/users/jaapz/events{/privacy}","received_events_url":"https://api.github.com/users/jaapz/received_events","type":"User","site_admin":false},"repo":{"id":36236037,"name":"werkzeug","full_name":"jaapz/werkzeug","owner":{"login":"jaapz","id":513050,"avatar_url":"https://avatars.githubusercontent.com/u/513050?v=3","gravatar_id":"","url":"https://api.github.com/users/jaapz","html_url":"https://github.com/jaapz","followers_url":"https://api.github.com/users/jaapz/followers","following_url":"https://api.github.com/users/jaapz/following{/other_user}","gists_url":"https://api.github.com/users/jaapz/gists{/gist_id}","starred_url":"https://api.github.com/users/jaapz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jaapz/subscriptions","organizations_url":"https://api.github.com/users/jaapz/orgs","repos_url":"https://api.github.com/users/jaapz/repos","events_url":"https://api.github.com/users/jaapz/events{/privacy}","received_events_url":"https://api.github.com/users/jaapz/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jaapz/werkzeug","description":"A flexible WSGI implementation and toolkit","fork":true,"url":"https://api.github.com/repos/jaapz/werkzeug","forks_url":"https://api.github.com/repos/jaapz/werkzeug/forks","keys_url":"https://api.github.com/repos/jaapz/werkzeug/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jaapz/werkzeug/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jaapz/werkzeug/teams","hooks_url":"https://api.github.com/repos/jaapz/werkzeug/hooks","issue_events_url":"https://api.github.com/repos/jaapz/werkzeug/issues/events{/number}","events_url":"https://api.github.com/repos/jaapz/werkzeug/events","assignees_url":"https://api.github.com/repos/jaapz/werkzeug/assignees{/user}","branches_url":"https://api.github.com/repos/jaapz/werkzeug/branches{/branch}","tags_url":"https://api.github.com/repos/jaapz/werkzeug/tags","blobs_url":"https://api.github.com/repos/jaapz/werkzeug/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jaapz/werkzeug/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jaapz/werkzeug/git/refs{/sha}","trees_url":"https://api.github.com/repos/jaapz/werkzeug/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jaapz/werkzeug/statuses/{sha}","languages_url":"https://api.github.com/repos/jaapz/werkzeug/languages","stargazers_url":"https://api.github.com/repos/jaapz/werkzeug/stargazers","contributors_url":"https://api.github.com/repos/jaapz/werkzeug/contributors","subscribers_url":"https://api.github.com/repos/jaapz/werkzeug/subscribers","subscription_url":"https://api.github.com/repos/jaapz/werkzeug/subscription","commits_url":"https://api.github.com/repos/jaapz/werkzeug/commits{/sha}","git_commits_url":"https://api.github.com/repos/jaapz/werkzeug/git/commits{/sha}","comments_url":"https://api.github.com/repos/jaapz/werkzeug/comments{/number}","issue_comment_url":"https://api.github.com/repos/jaapz/werkzeug/issues/comments{/number}","contents_url":"https://api.github.com/repos/jaapz/werkzeug/contents/{+path}","compare_url":"https://api.github.com/repos/jaapz/werkzeug/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jaapz/werkzeug/merges","archive_url":"https://api.github.com/repos/jaapz/werkzeug/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jaapz/werkzeug/downloads","issues_url":"https://api.github.com/repos/jaapz/werkzeug/issues{/number}","pulls_url":"https://api.github.com/repos/jaapz/werkzeug/pulls{/number}","milestones_url":"https://api.github.com/repos/jaapz/werkzeug/milestones{/number}","notifications_url":"https://api.github.com/repos/jaapz/werkzeug/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jaapz/werkzeug/labels{/name}","releases_url":"https://api.github.com/repos/jaapz/werkzeug/releases{/id}","created_at":"2015-05-25T14:35:34Z","updated_at":"2015-05-25T14:35:35Z","pushed_at":"2015-08-05T12:38:04Z","git_url":"git://github.com/jaapz/werkzeug.git","ssh_url":"git@github.com:jaapz/werkzeug.git","clone_url":"https://github.com/jaapz/werkzeug.git","svn_url":"https://github.com/jaapz/werkzeug","homepage":"http://werkzeug.pocoo.org/","size":12497,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"mitsuhiko:master","ref":"master","sha":"cc8c8396ecdbc25bedc1cfdddfe8df2387b72ae3","user":{"login":"mitsuhiko","id":7396,"avatar_url":"https://avatars.githubusercontent.com/u/7396?v=3","gravatar_id":"","url":"https://api.github.com/users/mitsuhiko","html_url":"https://github.com/mitsuhiko","followers_url":"https://api.github.com/users/mitsuhiko/followers","following_url":"https://api.github.com/users/mitsuhiko/following{/other_user}","gists_url":"https://api.github.com/users/mitsuhiko/gists{/gist_id}","starred_url":"https://api.github.com/users/mitsuhiko/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mitsuhiko/subscriptions","organizations_url":"https://api.github.com/users/mitsuhiko/orgs","repos_url":"https://api.github.com/users/mitsuhiko/repos","events_url":"https://api.github.com/users/mitsuhiko/events{/privacy}","received_events_url":"https://api.github.com/users/mitsuhiko/received_events","type":"User","site_admin":false},"repo":{"id":997338,"name":"werkzeug","full_name":"mitsuhiko/werkzeug","owner":{"login":"mitsuhiko","id":7396,"avatar_url":"https://avatars.githubusercontent.com/u/7396?v=3","gravatar_id":"","url":"https://api.github.com/users/mitsuhiko","html_url":"https://github.com/mitsuhiko","followers_url":"https://api.github.com/users/mitsuhiko/followers","following_url":"https://api.github.com/users/mitsuhiko/following{/other_user}","gists_url":"https://api.github.com/users/mitsuhiko/gists{/gist_id}","starred_url":"https://api.github.com/users/mitsuhiko/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mitsuhiko/subscriptions","organizations_url":"https://api.github.com/users/mitsuhiko/orgs","repos_url":"https://api.github.com/users/mitsuhiko/repos","events_url":"https://api.github.com/users/mitsuhiko/events{/privacy}","received_events_url":"https://api.github.com/users/mitsuhiko/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mitsuhiko/werkzeug","description":"A flexible WSGI implementation and toolkit","fork":false,"url":"https://api.github.com/repos/mitsuhiko/werkzeug","forks_url":"https://api.github.com/repos/mitsuhiko/werkzeug/forks","keys_url":"https://api.github.com/repos/mitsuhiko/werkzeug/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mitsuhiko/werkzeug/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mitsuhiko/werkzeug/teams","hooks_url":"https://api.github.com/repos/mitsuhiko/werkzeug/hooks","issue_events_url":"https://api.github.com/repos/mitsuhiko/werkzeug/issues/events{/number}","events_url":"https://api.github.com/repos/mitsuhiko/werkzeug/events","assignees_url":"https://api.github.com/repos/mitsuhiko/werkzeug/assignees{/user}","branches_url":"https://api.github.com/repos/mitsuhiko/werkzeug/branches{/branch}","tags_url":"https://api.github.com/repos/mitsuhiko/werkzeug/tags","blobs_url":"https://api.github.com/repos/mitsuhiko/werkzeug/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mitsuhiko/werkzeug/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mitsuhiko/werkzeug/git/refs{/sha}","trees_url":"https://api.github.com/repos/mitsuhiko/werkzeug/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mitsuhiko/werkzeug/statuses/{sha}","languages_url":"https://api.github.com/repos/mitsuhiko/werkzeug/languages","stargazers_url":"https://api.github.com/repos/mitsuhiko/werkzeug/stargazers","contributors_url":"https://api.github.com/repos/mitsuhiko/werkzeug/contributors","subscribers_url":"https://api.github.com/repos/mitsuhiko/werkzeug/subscribers","subscription_url":"https://api.github.com/repos/mitsuhiko/werkzeug/subscription","commits_url":"https://api.github.com/repos/mitsuhiko/werkzeug/commits{/sha}","git_commits_url":"https://api.github.com/repos/mitsuhiko/werkzeug/git/commits{/sha}","comments_url":"https://api.github.com/repos/mitsuhiko/werkzeug/comments{/number}","issue_comment_url":"https://api.github.com/repos/mitsuhiko/werkzeug/issues/comments{/number}","contents_url":"https://api.github.com/repos/mitsuhiko/werkzeug/contents/{+path}","compare_url":"https://api.github.com/repos/mitsuhiko/werkzeug/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mitsuhiko/werkzeug/merges","archive_url":"https://api.github.com/repos/mitsuhiko/werkzeug/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mitsuhiko/werkzeug/downloads","issues_url":"https://api.github.com/repos/mitsuhiko/werkzeug/issues{/number}","pulls_url":"https://api.github.com/repos/mitsuhiko/werkzeug/pulls{/number}","milestones_url":"https://api.github.com/repos/mitsuhiko/werkzeug/milestones{/number}","notifications_url":"https://api.github.com/repos/mitsuhiko/werkzeug/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mitsuhiko/werkzeug/labels{/name}","releases_url":"https://api.github.com/repos/mitsuhiko/werkzeug/releases{/id}","created_at":"2010-10-18T11:42:40Z","updated_at":"2015-08-05T03:20:02Z","pushed_at":"2015-08-05T19:01:28Z","git_url":"git://github.com/mitsuhiko/werkzeug.git","ssh_url":"git@github.com:mitsuhiko/werkzeug.git","clone_url":"https://github.com/mitsuhiko/werkzeug.git","svn_url":"https://github.com/mitsuhiko/werkzeug","homepage":"http://werkzeug.pocoo.org/","size":17565,"stargazers_count":2060,"watchers_count":2060,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":605,"mirror_url":null,"open_issues_count":118,"forks":605,"open_issues":118,"watchers":2060,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mitsuhiko/werkzeug/pulls/736"},"html":{"href":"https://github.com/mitsuhiko/werkzeug/pull/736"},"issue":{"href":"https://api.github.com/repos/mitsuhiko/werkzeug/issues/736"},"comments":{"href":"https://api.github.com/repos/mitsuhiko/werkzeug/issues/736/comments"},"review_comments":{"href":"https://api.github.com/repos/mitsuhiko/werkzeug/pulls/736/comments"},"review_comment":{"href":"https://api.github.com/repos/mitsuhiko/werkzeug/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mitsuhiko/werkzeug/pulls/736/commits"},"statuses":{"href":"https://api.github.com/repos/mitsuhiko/werkzeug/statuses/1fdc31d54737a72148cfdef701f352eadc2f0ff4"}}}}