1# mode: run
2# tag: pyclass, getattr
3
4"""
5Python bypasses __getattribute__ overrides for some special method lookups.
6"""
7
8lookups = []
9
10
11class PyClass(object):
12    """
13    >>> del lookups[:]
14    >>> obj = PyClass()
15    >>> obj.test
16    'getattribute(test)'
17    >>> lookups
18    ['getattribute(test)']
19    """
20    def __getattribute__(self, name):
21        lookup = 'getattribute(%s)' % name
22        lookups.append(lookup)
23        return lookup
24
25    def __getattr__(self, name):
26        lookup = 'getattr(%s)' % name
27        lookups.append(lookup)
28        return lookup
29
30
31def use_as_context_manager(obj):
32    """
33    >>> del lookups[:]
34    >>> class PyCM(PyClass):
35    ...     def __enter__(self): return '__enter__(%s)' % (self is obj or self)
36    ...     def __exit__(self, *args): pass
37    >>> obj = PyCM()
38    >>> use_as_context_manager(obj)
39    '__enter__(True)'
40    >>> lookups
41    []
42    """
43    with obj as x:
44        pass
45    return x
46