{"action":"created","issue":{"url":"https://api.github.com/repos/zopefoundation/Acquisition/issues/9","repository_url":"https://api.github.com/repos/zopefoundation/Acquisition","labels_url":"https://api.github.com/repos/zopefoundation/Acquisition/issues/9/labels{/name}","comments_url":"https://api.github.com/repos/zopefoundation/Acquisition/issues/9/comments","events_url":"https://api.github.com/repos/zopefoundation/Acquisition/issues/9/events","html_url":"https://github.com/zopefoundation/Acquisition/issues/9","id":76107922,"number":9,"title":"Pure-Python Wrapper objects break `object.__getattribute__` in methods of the wrapped object","user":{"login":"jamadden","id":1256082,"avatar_url":"https://avatars.githubusercontent.com/u/1256082?v=3","gravatar_id":"","url":"https://api.github.com/users/jamadden","html_url":"https://github.com/jamadden","followers_url":"https://api.github.com/users/jamadden/followers","following_url":"https://api.github.com/users/jamadden/following{/other_user}","gists_url":"https://api.github.com/users/jamadden/gists{/gist_id}","starred_url":"https://api.github.com/users/jamadden/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jamadden/subscriptions","organizations_url":"https://api.github.com/users/jamadden/orgs","repos_url":"https://api.github.com/users/jamadden/repos","events_url":"https://api.github.com/users/jamadden/events{/privacy}","received_events_url":"https://api.github.com/users/jamadden/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2015-05-13T20:11:03Z","updated_at":"2016-09-30T10:04:17Z","closed_at":"2015-05-19T20:34:18Z","body":"Certain \"base\" classes make direct use of `object.__getattribute__` in their method implementations. (i.e., *outside* of their own `__getattribute__` implementation). They may do this for performance reasons, or to simplify their implementation of `__getattribute__`.  One prominent example is `persistent.Persistent`, but there are undoubtedly others.\r\n\r\nIf classes like this are wrapped with a pure-Python acquisition wrapper, those methods fail, because the `self` they have is not the `self` they expect (it's the wrapper), and directly calling `object.__getattribute__` bypasses the wrapper's `__getattribute__` implementation.\r\n\r\nHere's an example test that fails with pure-Python, but works under the C implementation:\r\n\r\n```python\r\n    def test_object_getattribute_in_rebound_method(self):\r\n\r\n        class Persistent(object):\r\n            __slots__ = ('__flags')\r\n            def __init__(self):\r\n                self.__flags = 42\r\n\r\n            def get_flags(self):\r\n                return object.__getattribute__(self, '_Persistent__flags')\r\n\r\n        wrapped = Persistent()\r\n        wrapper = Acquisition.ImplicitAcquisitionWrapper(wrapped, None)\r\n\r\n        self.assertEqual(wrapped.get_flags(), wrapper.get_flags())\r\n```\r\n\r\nIt fails like so:\r\n```\r\n  File \"/Acquisition/tests.py\", line 3171, in test_object_getattribute_in_rebound_method\r\n    self.assertEqual(wrapped.get_flags(), wrapper.get_flags())\r\n  File \"/Acquisition/tests.py\", line 3166, in get_flags\r\n    return object.__getattribute__(self, '_Persistent__flags')\r\nAttributeError: 'ImplicitAcquisitionWrapper' object has no attribute '_Persistent__flags'\r\n```\r\n\r\nI'm trying to figure out how to fix this."},"comment":{"url":"https://api.github.com/repos/zopefoundation/Acquisition/issues/comments/250707852","html_url":"https://github.com/zopefoundation/Acquisition/issues/9#issuecomment-250707852","issue_url":"https://api.github.com/repos/zopefoundation/Acquisition/issues/9","id":250707852,"user":{"login":"dwt","id":57199,"avatar_url":"https://avatars.githubusercontent.com/u/57199?v=3","gravatar_id":"","url":"https://api.github.com/users/dwt","html_url":"https://github.com/dwt","followers_url":"https://api.github.com/users/dwt/followers","following_url":"https://api.github.com/users/dwt/following{/other_user}","gists_url":"https://api.github.com/users/dwt/gists{/gist_id}","starred_url":"https://api.github.com/users/dwt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dwt/subscriptions","organizations_url":"https://api.github.com/users/dwt/orgs","repos_url":"https://api.github.com/users/dwt/repos","events_url":"https://api.github.com/users/dwt/events{/privacy}","received_events_url":"https://api.github.com/users/dwt/received_events","type":"User","site_admin":false},"created_at":"2016-09-30T10:04:17Z","updated_at":"2016-09-30T10:04:17Z","body":"Hi @jamadden while trying to port this to python 3 we noticed that the combination of pure python Acquisition, AccessControll and RestrictedPython together breaks at this point.\r\n\r\nThe problem as best as I can describe it is, that there is no way to do a perfect proxy in python. In this case, that means that one cannot get at the `__dict__` of a class object in python 2.7, but always gets a `dict_proxy` instead, which then cannot be assigned as the `__dict__` of another instance.\r\n\r\nSo, can you please explain more about the use case in which this arose? We (at the Zope Resurrection Sprint in Halle) suspect that supporting `object.__getattribute__` may be something that does / should not happen outside of Zope itself - so can you name more use cases?\r\n\r\nTo be more specific, we think that also the pure python implementation of `persistant.Persistant` is probably not something we cannot support in the future (especially since there is a working C implementation that also works for python3).\r\n\r\nSo, can you please give some updates?"}}
{"actor":{"display_login":"dwt"}}