{"action":"created","issue":{"url":"https://api.github.com/repos/nigelsmall/py2neo/issues/391","repository_url":"https://api.github.com/repos/nigelsmall/py2neo","labels_url":"https://api.github.com/repos/nigelsmall/py2neo/issues/391/labels{/name}","comments_url":"https://api.github.com/repos/nigelsmall/py2neo/issues/391/comments","events_url":"https://api.github.com/repos/nigelsmall/py2neo/issues/391/events","html_url":"https://github.com/nigelsmall/py2neo/issues/391","id":60576212,"number":391,"title":"Known bug in WeakValueDictionary's setdefault() causes issues in Node,Rel and Relationship caches in multithreaded environments ","user":{"login":"fallonchen","id":7786007,"avatar_url":"https://avatars.githubusercontent.com/u/7786007?v=3","gravatar_id":"","url":"https://api.github.com/users/fallonchen","html_url":"https://github.com/fallonchen","followers_url":"https://api.github.com/users/fallonchen/followers","following_url":"https://api.github.com/users/fallonchen/following{/other_user}","gists_url":"https://api.github.com/users/fallonchen/gists{/gist_id}","starred_url":"https://api.github.com/users/fallonchen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fallonchen/subscriptions","organizations_url":"https://api.github.com/users/fallonchen/orgs","repos_url":"https://api.github.com/users/fallonchen/repos","events_url":"https://api.github.com/users/fallonchen/events{/privacy}","received_events_url":"https://api.github.com/users/fallonchen/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/nigelsmall/py2neo/labels/bug","name":"bug","color":"e10c02"}],"state":"closed","locked":false,"assignee":{"login":"nigelsmall","id":275311,"avatar_url":"https://avatars.githubusercontent.com/u/275311?v=3","gravatar_id":"","url":"https://api.github.com/users/nigelsmall","html_url":"https://github.com/nigelsmall","followers_url":"https://api.github.com/users/nigelsmall/followers","following_url":"https://api.github.com/users/nigelsmall/following{/other_user}","gists_url":"https://api.github.com/users/nigelsmall/gists{/gist_id}","starred_url":"https://api.github.com/users/nigelsmall/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nigelsmall/subscriptions","organizations_url":"https://api.github.com/users/nigelsmall/orgs","repos_url":"https://api.github.com/users/nigelsmall/repos","events_url":"https://api.github.com/users/nigelsmall/events{/privacy}","received_events_url":"https://api.github.com/users/nigelsmall/received_events","type":"User","site_admin":false},"assignees":[{"login":"nigelsmall","id":275311,"avatar_url":"https://avatars.githubusercontent.com/u/275311?v=3","gravatar_id":"","url":"https://api.github.com/users/nigelsmall","html_url":"https://github.com/nigelsmall","followers_url":"https://api.github.com/users/nigelsmall/followers","following_url":"https://api.github.com/users/nigelsmall/following{/other_user}","gists_url":"https://api.github.com/users/nigelsmall/gists{/gist_id}","starred_url":"https://api.github.com/users/nigelsmall/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nigelsmall/subscriptions","organizations_url":"https://api.github.com/users/nigelsmall/orgs","repos_url":"https://api.github.com/users/nigelsmall/repos","events_url":"https://api.github.com/users/nigelsmall/events{/privacy}","received_events_url":"https://api.github.com/users/nigelsmall/received_events","type":"User","site_admin":false}],"milestone":{"url":"https://api.github.com/repos/nigelsmall/py2neo/milestones/22","html_url":"https://github.com/nigelsmall/py2neo/milestones/Release%202.0.6","labels_url":"https://api.github.com/repos/nigelsmall/py2neo/milestones/22/labels","id":1008996,"number":22,"title":"Release 2.0.6","description":"","creator":{"login":"nigelsmall","id":275311,"avatar_url":"https://avatars.githubusercontent.com/u/275311?v=3","gravatar_id":"","url":"https://api.github.com/users/nigelsmall","html_url":"https://github.com/nigelsmall","followers_url":"https://api.github.com/users/nigelsmall/followers","following_url":"https://api.github.com/users/nigelsmall/following{/other_user}","gists_url":"https://api.github.com/users/nigelsmall/gists{/gist_id}","starred_url":"https://api.github.com/users/nigelsmall/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nigelsmall/subscriptions","organizations_url":"https://api.github.com/users/nigelsmall/orgs","repos_url":"https://api.github.com/users/nigelsmall/repos","events_url":"https://api.github.com/users/nigelsmall/events{/privacy}","received_events_url":"https://api.github.com/users/nigelsmall/received_events","type":"User","site_admin":false},"open_issues":0,"closed_issues":4,"state":"closed","created_at":"2015-03-06T10:00:14Z","updated_at":"2015-04-07T10:04:39Z","due_on":null,"closed_at":"2015-04-07T10:04:39Z"},"comments":13,"created_at":"2015-03-10T21:57:20Z","updated_at":"2016-07-29T06:19:50Z","closed_at":"2015-04-07T08:33:25Z","body":"WeakValueDictionary.setdefault() and WeakValueDictionary.pop() will sometimes return None in multithreaded environments, as explained here http://bugs.python.org/issue19542. The patch is pending review.\r\n\r\nI've been able to reproduce the problem by running the test case x.py that's linked in the bug report using both python 2.7.9 and python 3.4.3. \r\n\r\nI have also encountered the problem during development of a Flask app that uses py2neo. This app is run on Apache using mod_wsgi-express (prefork, 1 process, 5 threads). \r\n\r\nAnyhow, since Node.cache, Rel.cache, and Relationship.cache all inherit from WeakValueDictionary and have methods that call setdefault(), I've been seeing NoneType errors in my Flask app. \r\n\r\nFor instance, this snippet in Rel#hydrate() in core.py:\r\n ``` \r\n        if inst is None:\r\n            new_inst = cls()\r\n            new_inst.__stale.update({\"properties\"})\r\n            inst = cls.cache.setdefault(self, new_inst)\r\n\r\n        cls.cache[self] = inst\r\n```\r\nWill intermittently produce:\r\n```\r\n    File \"/Users/fallonchen/.virtualenvs/ul06/lib/python2.7/site-packages/py2neo/core.py\", line 912, in match\r\n    for result in results:\r\n    File \"/Users/fallonchen/.virtualenvs/ul06/lib/python2.7/site-packages/py2neo/cypher/core.py\", line 453, in next\r\n    return self.__next__()\r\n    File \"/Users/fallonchen/.virtualenvs/ul06/lib/python2.7/site-packages/py2neo/cypher/core.py\", line 450, in __next__\r\n    return next(self.__response_item)\r\n    File \"/Users/fallonchen/.virtualenvs/ul06/lib/python2.7/site-packages/py2neo/cypher/core.py\", line 443, in __response_iterator\r\n    yield producer.produce(self.graph.hydrate(assembled(record_data)))\r\n    File \"/Users/fallonchen/.virtualenvs/ul06/lib/python2.7/site-packages/py2neo/core.py\", line 839, in hydrate\r\n    return type(data)(map(self.hydrate, data))\r\n    File \"/Users/fallonchen/.virtualenvs/ul06/lib/python2.7/site-packages/py2neo/core.py\", line 806, in hydrate\r\n    return Relationship.hydrate(data)\r\n    File \"/Users/fallonchen/.virtualenvs/ul06/lib/python2.7/site-packages/py2neo/core.py\", line 2421, in hydrate\r\n    Rel.hydrate(data),\r\n    File \"/Users/fallonchen/.virtualenvs/ul06/lib/python2.7/site-packages/py2neo/core.py\", line 1769, in hydrate\r\n    cls.cache[self] = inst\r\n    File \"/usr/local/Cellar/python/2.7.8_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/weakref.py\", line 103, in __setitem__\r\n    self.data[key] = KeyedRef(value, self._remove, key)\r\n    File \"/usr/local/Cellar/python/2.7.8_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/weakref.py\", line 267, in __new__\r\n    self = ref.__new__(type, ob, callback)\r\n    TypeError: cannot create weak reference to 'NoneType' object\r\n\r\n```\r\n\r\nI've found that you can get around the problem by replacing setdefault() with:\r\n\r\n            if self not in cls.cache:\r\n                 cls.cache[self] = new_inst\r\n             inst = cls.cache[self]\r\n\r\nIs this a good approach? I haven't looked too deeply into whether or not pop() is called, but I assume that it would also have to be patched. "},"comment":{"url":"https://api.github.com/repos/nigelsmall/py2neo/issues/comments/236103576","html_url":"https://github.com/nigelsmall/py2neo/issues/391#issuecomment-236103576","issue_url":"https://api.github.com/repos/nigelsmall/py2neo/issues/391","id":236103576,"user":{"login":"horejsek","id":749088,"avatar_url":"https://avatars.githubusercontent.com/u/749088?v=3","gravatar_id":"","url":"https://api.github.com/users/horejsek","html_url":"https://github.com/horejsek","followers_url":"https://api.github.com/users/horejsek/followers","following_url":"https://api.github.com/users/horejsek/following{/other_user}","gists_url":"https://api.github.com/users/horejsek/gists{/gist_id}","starred_url":"https://api.github.com/users/horejsek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/horejsek/subscriptions","organizations_url":"https://api.github.com/users/horejsek/orgs","repos_url":"https://api.github.com/users/horejsek/repos","events_url":"https://api.github.com/users/horejsek/events{/privacy}","received_events_url":"https://api.github.com/users/horejsek/received_events","type":"User","site_admin":false},"created_at":"2016-07-29T06:19:50Z","updated_at":"2016-07-29T06:19:50Z","body":"I upgraded to py2neo 3.1.1 (using Python 3.5.0 on Debian Wheezy) and still see this error."}}
{"actor":{"display_login":"horejsek"}}