1# mode: run 2 3# __getattribute__ and __getattr__ special methods and subclasses. 4 5cdef class boring: 6 cdef readonly int boring_member 7 cdef readonly int getattr_called 8 cdef int getattribute_called 9 def __init__(self): 10 self.boring_member = 10 11 12cdef class getattr_boring(boring): 13 """ 14 getattr does not override members. 15 16 >>> a = getattr_boring() 17 >>> a.boring_member 18 10 19 >>> a.getattr_called 20 0 21 >>> print(a.resolved_by) 22 getattr_boring 23 >>> a.getattr_called 24 1 25 >>> a.no_such_member 26 Traceback (most recent call last): 27 AttributeError 28 >>> a.getattr_called 29 2 30 """ 31 def __getattr__(self,n): 32 self.getattr_called += 1 33 if n == 'resolved_by': 34 return 'getattr_boring' 35 elif n == 'getattr_boring': 36 return True 37 else: 38 raise AttributeError 39 40 41# currently fails, see #1793 42#class getattr_boring_py(getattr_boring): 43# __doc__ = getattr_boring.__doc__.replace( 44# 'getattr_boring()', 'getattr_boring_py()') 45 46 47cdef class getattribute_boring(boring): 48 """ 49 getattribute overrides members. 50 51 >>> a = getattribute_boring() 52 >>> a.getattribute_called 53 1 54 >>> a.boring_member 55 Traceback (most recent call last): 56 AttributeError 57 >>> a.getattribute_called 58 3 59 >>> print(a.resolved_by) 60 getattribute_boring 61 >>> a.getattribute_called 62 5 63 >>> a.no_such_member 64 Traceback (most recent call last): 65 AttributeError 66 >>> a.getattribute_called 67 7 68 """ 69 def __getattribute__(self,n): 70 self.getattribute_called += 1 71 if n == 'resolved_by': 72 return 'getattribute_boring' 73 elif n == 'getattribute_boring': 74 return True 75 elif n == 'getattribute_called': 76 return self.getattribute_called 77 else: 78 raise AttributeError 79 80 81class getattribute_boring_py(getattribute_boring): 82 __doc__ = getattribute_boring.__doc__.replace( 83 'getattribute_boring()', 'getattribute_boring_py()') 84 85 86cdef class _getattr: 87 cdef readonly int getattr_called 88 def __getattr__(self,n): 89 self.getattr_called += 1 90 if n == 'resolved_by': 91 return '_getattr' 92 elif n == '_getattr': 93 return True 94 elif n == 'getattr_called': 95 # must only get here if __getattribute__ is overwritten 96 assert 'getattribute' in type(self).__name__ 97 return self.getattr_called 98 else: 99 raise AttributeError 100 101 102class getattr_py(_getattr): 103 """ 104 getattr is inherited. 105 106 >>> a = getattr_py() 107 >>> a.getattr_called 108 0 109 >>> print(a.resolved_by) 110 _getattr 111 >>> a.getattr_called 112 1 113 >>> print(a._getattr) 114 True 115 >>> a.getattr_called 116 2 117 >>> a.no_such_member 118 Traceback (most recent call last): 119 AttributeError 120 121 # currently fails, see #1793 122 #>>> a.getattr_called 123 #3 124 """ 125 126 127cdef class _getattribute: 128 cdef int getattribute_called 129 def __getattribute__(self,n): 130 self.getattribute_called += 1 131 if n == 'resolved_by': 132 return '_getattribute' 133 elif n == '_getattribute': 134 return True 135 elif n == 'getattribute_called': 136 return self.getattribute_called 137 else: 138 raise AttributeError 139 140 141class getattribute_py(_getattribute): 142 """ 143 getattribute is inherited. 144 145 >>> a = getattribute_py() 146 >>> a.getattribute_called 147 1 148 >>> print(a.resolved_by) 149 _getattribute 150 >>> a.getattribute_called 151 3 152 >>> print(a._getattribute) 153 True 154 >>> a.getattribute_called 155 5 156 >>> a.no_such_member 157 Traceback (most recent call last): 158 AttributeError 159 >>> a.getattribute_called 160 7 161 """ 162 163 164cdef class boring_getattribute(_getattribute): 165 cdef readonly int boring_getattribute_member 166 167cdef class boring_boring_getattribute(boring_getattribute): 168 """ 169 getattribute is inherited. 170 171 >>> a = boring_boring_getattribute() 172 >>> a.getattribute_called 173 1 174 >>> a.boring_getattribute_member 175 Traceback (most recent call last): 176 AttributeError 177 >>> a.getattribute_called 178 3 179 >>> a.boring_boring_getattribute_member 180 Traceback (most recent call last): 181 AttributeError 182 >>> a.getattribute_called 183 5 184 >>> print(a.resolved_by) 185 _getattribute 186 >>> a.getattribute_called 187 7 188 >>> a.no_such_member 189 Traceback (most recent call last): 190 AttributeError 191 >>> a.getattribute_called 192 9 193 """ 194 cdef readonly int boring_boring_getattribute_member 195 196 197class boring_boring_getattribute_py(boring_boring_getattribute): 198 __doc__ = boring_boring_getattribute.__doc__.replace( 199 'boring_boring_getattribute()', 'boring_boring_getattribute_py()') 200 201 202cdef class boring_getattr(_getattr): 203 cdef readonly int boring_getattr_member 204 205cdef class boring_boring_getattr(boring_getattr): 206 cdef readonly int boring_boring_getattr_member 207 208cdef class getattribute_boring_boring_getattr(boring_boring_getattr): 209 """ 210 __getattribute__ is always tried first, then __getattr__, regardless of where 211 in the inheritance hierarchy they came from. 212 213 >>> a = getattribute_boring_boring_getattr() 214 >>> (a.getattr_called, a.getattribute_called) 215 (1, 2) 216 >>> print(a.resolved_by) 217 getattribute_boring_boring_getattr 218 >>> (a.getattr_called, a.getattribute_called) 219 (2, 5) 220 >>> a.getattribute_boring_boring_getattr 221 True 222 >>> (a.getattr_called, a.getattribute_called) 223 (3, 8) 224 >>> a._getattr 225 True 226 >>> (a.getattr_called, a.getattribute_called) 227 (5, 11) 228 >>> a.no_such_member 229 Traceback (most recent call last): 230 AttributeError 231 >>> (a.getattr_called, a.getattribute_called) 232 (7, 14) 233 """ 234 cdef int getattribute_called 235 def __getattribute__(self,n): 236 self.getattribute_called += 1 237 if n == 'resolved_by': 238 return 'getattribute_boring_boring_getattr' 239 elif n == 'getattribute_boring_boring_getattr': 240 return True 241 elif n == 'getattribute_called': 242 return self.getattribute_called 243 else: 244 raise AttributeError 245 246 247# currently fails, see #1793 248#class getattribute_boring_boring_getattr_py(getattribute_boring_boring_getattr): 249# __doc__ = getattribute_boring_boring_getattr.__doc__.replace( 250# 'getattribute_boring_boring_getattr()', 'getattribute_boring_boring_getattr_py()') 251 252 253cdef class getattr_boring_boring_getattribute(boring_boring_getattribute): 254 """ 255 __getattribute__ is always tried first, then __getattr__, regardless of where 256 in the inheritance hierarchy they came from. 257 258 >>> a = getattr_boring_boring_getattribute() 259 >>> (a.getattr_called, a.getattribute_called) 260 (1, 2) 261 >>> print(a.resolved_by) 262 _getattribute 263 >>> (a.getattr_called, a.getattribute_called) 264 (2, 5) 265 >>> a.getattr_boring_boring_getattribute 266 True 267 >>> (a.getattr_called, a.getattribute_called) 268 (4, 8) 269 >>> a._getattribute 270 True 271 >>> (a.getattr_called, a.getattribute_called) 272 (5, 11) 273 >>> a.no_such_member 274 Traceback (most recent call last): 275 AttributeError 276 >>> (a.getattr_called, a.getattribute_called) 277 (7, 14) 278 """ 279 cdef readonly int getattr_called # note: property will not be used due to __getattribute__() 280 def __getattr__(self,n): 281 self.getattr_called += 1 282 if n == 'resolved_by': 283 return 'getattr_boring_boring_getattribute' 284 elif n == 'getattr_boring_boring_getattribute': 285 return True 286 elif n == 'getattr_called': 287 return self.getattr_called 288 else: 289 raise AttributeError 290 291 292# currently fails, see #1793 293#class getattr_boring_boring_getattribute_py(getattr_boring_boring_getattribute): 294# __doc__ = getattr_boring_boring_getattribute.__doc__.replace( 295# 'getattr_boring_boring_getattribute()', 'getattr_boring_boring_getattribute_py()') 296