Total Complexity | 103 |
Total Lines | 351 |
Duplicated Lines | 0 % |
Complex classes like src.lazy_object_proxy.Proxy often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | import operator |
||
64 | class Proxy(with_metaclass(_ProxyMetaType)): |
||
65 | """ |
||
66 | A proxy implementation in pure Python, using slots. You can subclass this to add |
||
67 | local methods or attributes, or enable __dict__. |
||
68 | |||
69 | The most important internals: |
||
70 | |||
71 | * ``__factory__`` is the callback that "materializes" the object we proxy to. |
||
72 | * ``__target__`` will contain the object we proxy to, once it's "materialized". |
||
73 | * ``__wrapped__`` is a property that does either: |
||
74 | |||
75 | * return ``__target__`` if it's set. |
||
76 | * calls ``__factory__``, saves result to ``__target__`` and returns said result. |
||
77 | """ |
||
78 | |||
79 | __slots__ = '__target__', '__factory__' |
||
80 | |||
81 | def __init__(self, factory): |
||
82 | object.__setattr__(self, '__factory__', factory) |
||
83 | |||
84 | @property |
||
85 | def __wrapped__(self, __getattr__=object.__getattribute__, __setattr__=object.__setattr__, |
||
86 | __delattr__=object.__delattr__): |
||
87 | try: |
||
88 | return __getattr__(self, '__target__') |
||
89 | except AttributeError: |
||
90 | try: |
||
91 | factory = __getattr__(self, '__factory__') |
||
92 | except AttributeError: |
||
93 | raise ValueError("Proxy hasn't been initiated: __factory__ is missing.") |
||
94 | target = factory() |
||
95 | __setattr__(self, '__target__', target) |
||
96 | return target |
||
97 | |||
98 | @__wrapped__.deleter |
||
99 | def __wrapped__(self, __delattr__=object.__delattr__): |
||
100 | __delattr__(self, '__target__') |
||
101 | |||
102 | @__wrapped__.setter |
||
103 | def __wrapped__(self, target, __setattr__=object.__setattr__): |
||
104 | __setattr__(self, '__target__', target) |
||
105 | |||
106 | @property |
||
107 | def __name__(self): |
||
108 | return self.__wrapped__.__name__ |
||
109 | |||
110 | @__name__.setter |
||
111 | def __name__(self, value): |
||
112 | self.__wrapped__.__name__ = value |
||
113 | |||
114 | @property |
||
115 | def __class__(self): |
||
116 | return self.__wrapped__.__class__ |
||
117 | |||
118 | @__class__.setter |
||
119 | def __class__(self, value): |
||
120 | self.__wrapped__.__class__ = value |
||
121 | |||
122 | @property |
||
123 | def __annotations__(self): |
||
124 | return self.__wrapped__.__anotations__ |
||
125 | |||
126 | @__annotations__.setter |
||
127 | def __annotations__(self, value): |
||
128 | self.__wrapped__.__annotations__ = value |
||
129 | |||
130 | def __dir__(self): |
||
131 | return dir(self.__wrapped__) |
||
132 | |||
133 | def __str__(self): |
||
134 | return str(self.__wrapped__) |
||
135 | |||
136 | if PY3: |
||
137 | def __bytes__(self): |
||
138 | return bytes(self.__wrapped__) |
||
139 | |||
140 | def __repr__(self, __getattr__=object.__getattribute__): |
||
141 | try: |
||
142 | target = __getattr__(self, '__target__') |
||
143 | except AttributeError: |
||
144 | return '<%s at 0x%x with factory %r>' % ( |
||
145 | type(self).__name__, id(self), |
||
146 | self.__factory__ |
||
147 | ) |
||
148 | else: |
||
149 | return '<%s at 0x%x wrapping %r at 0x%x with factory %r>' % ( |
||
150 | type(self).__name__, id(self), |
||
151 | target, id(target), |
||
152 | self.__factory__ |
||
153 | ) |
||
154 | |||
155 | def __reversed__(self): |
||
156 | return reversed(self.__wrapped__) |
||
157 | |||
158 | if PY3: |
||
159 | def __round__(self): |
||
160 | return round(self.__wrapped__) |
||
161 | |||
162 | def __lt__(self, other): |
||
163 | return self.__wrapped__ < other |
||
164 | |||
165 | def __le__(self, other): |
||
166 | return self.__wrapped__ <= other |
||
167 | |||
168 | def __eq__(self, other): |
||
169 | return self.__wrapped__ == other |
||
170 | |||
171 | def __ne__(self, other): |
||
172 | return self.__wrapped__ != other |
||
173 | |||
174 | def __gt__(self, other): |
||
175 | return self.__wrapped__ > other |
||
176 | |||
177 | def __ge__(self, other): |
||
178 | return self.__wrapped__ >= other |
||
179 | |||
180 | def __hash__(self): |
||
181 | return hash(self.__wrapped__) |
||
182 | |||
183 | def __nonzero__(self): |
||
184 | return bool(self.__wrapped__) |
||
185 | |||
186 | def __bool__(self): |
||
187 | return bool(self.__wrapped__) |
||
188 | |||
189 | def __setattr__(self, name, value, __setattr__=object.__setattr__): |
||
190 | if hasattr(type(self), name): |
||
191 | __setattr__(self, name, value) |
||
192 | else: |
||
193 | setattr(self.__wrapped__, name, value) |
||
194 | |||
195 | def __getattr__(self, name): |
||
196 | if name in ('__wrapped__', '__factory__'): |
||
197 | raise AttributeError(name) |
||
198 | else: |
||
199 | return getattr(self.__wrapped__, name) |
||
200 | |||
201 | def __delattr__(self, name, __delattr__=object.__delattr__): |
||
202 | if hasattr(type(self), name): |
||
203 | __delattr__(self, name) |
||
204 | else: |
||
205 | delattr(self.__wrapped__, name) |
||
206 | |||
207 | def __add__(self, other): |
||
208 | return self.__wrapped__ + other |
||
209 | |||
210 | def __sub__(self, other): |
||
211 | return self.__wrapped__ - other |
||
212 | |||
213 | def __mul__(self, other): |
||
214 | return self.__wrapped__ * other |
||
215 | |||
216 | def __div__(self, other): |
||
217 | return operator.div(self.__wrapped__, other) |
||
218 | |||
219 | def __truediv__(self, other): |
||
220 | return operator.truediv(self.__wrapped__, other) |
||
221 | |||
222 | def __floordiv__(self, other): |
||
223 | return self.__wrapped__ // other |
||
224 | |||
225 | def __mod__(self, other): |
||
226 | return self.__wrapped__ ^ other |
||
227 | |||
228 | def __divmod__(self, other): |
||
229 | return divmod(self.__wrapped__, other) |
||
230 | |||
231 | def __pow__(self, other, *args): |
||
232 | return pow(self.__wrapped__, other, *args) |
||
233 | |||
234 | def __lshift__(self, other): |
||
235 | return self.__wrapped__ << other |
||
236 | |||
237 | def __rshift__(self, other): |
||
238 | return self.__wrapped__ >> other |
||
239 | |||
240 | def __and__(self, other): |
||
241 | return self.__wrapped__ & other |
||
242 | |||
243 | def __xor__(self, other): |
||
244 | return self.__wrapped__ ^ other |
||
245 | |||
246 | def __or__(self, other): |
||
247 | return self.__wrapped__ | other |
||
248 | |||
249 | def __radd__(self, other): |
||
250 | return other + self.__wrapped__ |
||
251 | |||
252 | def __rsub__(self, other): |
||
253 | return other - self.__wrapped__ |
||
254 | |||
255 | def __rmul__(self, other): |
||
256 | return other * self.__wrapped__ |
||
257 | |||
258 | def __rdiv__(self, other): |
||
259 | return operator.div(other, self.__wrapped__) |
||
260 | |||
261 | def __rtruediv__(self, other): |
||
262 | return operator.truediv(other, self.__wrapped__) |
||
263 | |||
264 | def __rfloordiv__(self, other): |
||
265 | return other // self.__wrapped__ |
||
266 | |||
267 | def __rmod__(self, other): |
||
268 | return other % self.__wrapped__ |
||
269 | |||
270 | def __rdivmod__(self, other): |
||
271 | return divmod(other, self.__wrapped__) |
||
272 | |||
273 | def __rpow__(self, other, *args): |
||
274 | return pow(other, self.__wrapped__, *args) |
||
275 | |||
276 | def __rlshift__(self, other): |
||
277 | return other << self.__wrapped__ |
||
278 | |||
279 | def __rrshift__(self, other): |
||
280 | return other >> self.__wrapped__ |
||
281 | |||
282 | def __rand__(self, other): |
||
283 | return other & self.__wrapped__ |
||
284 | |||
285 | def __rxor__(self, other): |
||
286 | return other ^ self.__wrapped__ |
||
287 | |||
288 | def __ror__(self, other): |
||
289 | return other | self.__wrapped__ |
||
290 | |||
291 | def __iadd__(self, other): |
||
292 | self.__wrapped__ += other |
||
293 | return self |
||
294 | |||
295 | def __isub__(self, other): |
||
296 | self.__wrapped__ -= other |
||
297 | return self |
||
298 | |||
299 | def __imul__(self, other): |
||
300 | self.__wrapped__ *= other |
||
301 | return self |
||
302 | |||
303 | def __idiv__(self, other): |
||
304 | self.__wrapped__ = operator.idiv(self.__wrapped__, other) |
||
305 | return self |
||
306 | |||
307 | def __itruediv__(self, other): |
||
308 | self.__wrapped__ = operator.itruediv(self.__wrapped__, other) |
||
309 | return self |
||
310 | |||
311 | def __ifloordiv__(self, other): |
||
312 | self.__wrapped__ //= other |
||
313 | return self |
||
314 | |||
315 | def __imod__(self, other): |
||
316 | self.__wrapped__ %= other |
||
317 | return self |
||
318 | |||
319 | def __ipow__(self, other): |
||
320 | self.__wrapped__ **= other |
||
321 | return self |
||
322 | |||
323 | def __ilshift__(self, other): |
||
324 | self.__wrapped__ <<= other |
||
325 | return self |
||
326 | |||
327 | def __irshift__(self, other): |
||
328 | self.__wrapped__ >>= other |
||
329 | return self |
||
330 | |||
331 | def __iand__(self, other): |
||
332 | self.__wrapped__ &= other |
||
333 | return self |
||
334 | |||
335 | def __ixor__(self, other): |
||
336 | self.__wrapped__ ^= other |
||
337 | return self |
||
338 | |||
339 | def __ior__(self, other): |
||
340 | self.__wrapped__ |= other |
||
341 | return self |
||
342 | |||
343 | def __neg__(self): |
||
344 | return -self.__wrapped__ |
||
345 | |||
346 | def __pos__(self): |
||
347 | return +self.__wrapped__ |
||
348 | |||
349 | def __abs__(self): |
||
350 | return abs(self.__wrapped__) |
||
351 | |||
352 | def __invert__(self): |
||
353 | return ~self.__wrapped__ |
||
354 | |||
355 | def __int__(self): |
||
356 | return int(self.__wrapped__) |
||
357 | |||
358 | if PY2: |
||
359 | def __long__(self): |
||
360 | return long(self.__wrapped__) # flake8: noqa |
||
361 | |||
362 | def __float__(self): |
||
363 | return float(self.__wrapped__) |
||
364 | |||
365 | def __oct__(self): |
||
366 | return oct(self.__wrapped__) |
||
367 | |||
368 | def __hex__(self): |
||
369 | return hex(self.__wrapped__) |
||
370 | |||
371 | def __index__(self): |
||
372 | return operator.index(self.__wrapped__) |
||
373 | |||
374 | def __len__(self): |
||
375 | return len(self.__wrapped__) |
||
376 | |||
377 | def __contains__(self, value): |
||
378 | return value in self.__wrapped__ |
||
379 | |||
380 | def __getitem__(self, key): |
||
381 | return self.__wrapped__[key] |
||
382 | |||
383 | def __setitem__(self, key, value): |
||
384 | self.__wrapped__[key] = value |
||
385 | |||
386 | def __delitem__(self, key): |
||
387 | del self.__wrapped__[key] |
||
388 | |||
389 | def __getslice__(self, i, j): |
||
390 | return self.__wrapped__[i:j] |
||
391 | |||
392 | def __setslice__(self, i, j, value): |
||
393 | self.__wrapped__[i:j] = value |
||
394 | |||
395 | def __delslice__(self, i, j): |
||
396 | del self.__wrapped__[i:j] |
||
397 | |||
398 | def __enter__(self): |
||
399 | return self.__wrapped__.__enter__() |
||
400 | |||
401 | def __exit__(self, *args, **kwargs): |
||
402 | return self.__wrapped__.__exit__(*args, **kwargs) |
||
403 | |||
404 | def __iter__(self): |
||
405 | return iter(self.__wrapped__) |
||
406 | |||
407 | def __call__(self, *args, **kwargs): |
||
408 | return self.__wrapped__(*args, **kwargs) |
||
409 | |||
410 | def __reduce__(self): |
||
411 | return identity, (self.__wrapped__,) |
||
412 | |||
413 | def __reduce_ex__(self, protocol): |
||
414 | return identity, (self.__wrapped__,) |
||
415 |