Try to make an object not exhibit side-effects on attribute lookup.
(self)
| 84 | self._obj = obj |
| 85 | |
| 86 | def __enter__(self) -> None: |
| 87 | """Try to make an object not exhibit side-effects on attribute |
| 88 | lookup.""" |
| 89 | type_ = type(self._obj) |
| 90 | # Dark magic: |
| 91 | # If __getattribute__ doesn't exist on the class and __getattr__ does |
| 92 | # then __getattr__ will be called when doing |
| 93 | # getattr(type_, '__getattribute__', None) |
| 94 | # so we need to first remove the __getattr__, then the |
| 95 | # __getattribute__, then look up the attributes and then restore the |
| 96 | # original methods. :-( |
| 97 | # The upshot being that introspecting on an object to display its |
| 98 | # attributes will avoid unwanted side-effects. |
| 99 | __getattr__ = getattr(type_, "__getattr__", None) |
| 100 | if __getattr__ is not None: |
| 101 | try: |
| 102 | setattr(type_, "__getattr__", (lambda *_, **__: None)) |
| 103 | except (TypeError, AttributeError): |
| 104 | __getattr__ = None |
| 105 | __getattribute__ = getattr(type_, "__getattribute__", None) |
| 106 | if __getattribute__ is not None: |
| 107 | try: |
| 108 | setattr(type_, "__getattribute__", object.__getattribute__) |
| 109 | except (TypeError, AttributeError): |
| 110 | # XXX: This happens for e.g. built-in types |
| 111 | __getattribute__ = None |
| 112 | self._attribs = (__getattribute__, __getattr__) |
| 113 | # /Dark magic |
| 114 | |
| 115 | def __exit__( |
| 116 | self, |
nothing calls this directly
no outgoing calls
no test coverage detected