Completed
Push — master ( b2b0a5...3849b1 )
by Ionel Cristian
57s
created

src.lazy_object_proxy.Proxy   F

Complexity

Total Complexity 103

Size/Duplication

Total Lines 351
Duplicated Lines 0 %
Metric Value
dl 0
loc 351
rs 1.5789
wmc 103

63 Methods

Rating   Name   Duplication   Size   Complexity  
A Proxy.__lshift__() 0 2 1
A Proxy.__mul__() 0 2 1
A Proxy.__setitem__() 0 2 1
A Proxy.__invert__() 0 2 1
A Proxy.__ge__() 0 2 1
A Proxy.__reversed__() 0 2 1
A Proxy.__long__() 0 2 1
A Proxy.__divmod__() 0 2 1
A Proxy.__iand__() 0 3 1
A Proxy.__imod__() 0 3 1
A Proxy.__le__() 0 2 1
A Proxy.__ne__() 0 2 1
A Proxy.__lt__() 0 2 1
A Proxy.__nonzero__() 0 2 1
A Proxy.__abs__() 0 2 1
A Proxy.__delitem__() 0 2 1
A Proxy.__rshift__() 0 2 1
A Proxy.__float__() 0 2 1
A Proxy.__mod__() 0 2 1
A Proxy.__pow__() 0 2 1
A Proxy.__or__() 0 2 1
A Proxy.__itruediv__() 0 3 1
A Proxy.__ifloordiv__() 0 3 1
A Proxy.__imul__() 0 3 1
A Proxy.__ipow__() 0 3 1
A Proxy.__neg__() 0 2 1
A Proxy.__bool__() 0 2 1
A Proxy.__hash__() 0 2 1
A Proxy.__annotations__() 0 3 1
A Proxy.__bytes__() 0 2 1
A Proxy.__getslice__() 0 2 1
A Proxy.__div__() 0 2 1
A Proxy.__iter__() 0 2 1
A Proxy.__dir__() 0 2 1
A Proxy.__iadd__() 0 3 1
A Proxy.__ilshift__() 0 3 1
A Proxy.__idiv__() 0 3 1
A Proxy.__gt__() 0 2 1
A Proxy.__setslice__() 0 2 1
A Proxy.__isub__() 0 3 1
A Proxy.__class__() 0 3 1
A Proxy.__index__() 0 2 1
A Proxy.__xor__() 0 2 1
A Proxy.__pos__() 0 2 1
A Proxy.__delslice__() 0 2 1
A Proxy.__sub__() 0 2 1
A Proxy.__int__() 0 2 1
A Proxy.__contains__() 0 2 1
A Proxy.__and__() 0 2 1
A Proxy.__eq__() 0 2 1
A Proxy.__len__() 0 2 1
A Proxy.__name__() 0 3 1
A Proxy.__ixor__() 0 3 1
A Proxy.__floordiv__() 0 2 1
A Proxy.__ior__() 0 3 1
A Proxy.__round__() 0 2 1
A Proxy.__irshift__() 0 3 1
A Proxy.__hex__() 0 2 1
A Proxy.__getitem__() 0 2 1
A Proxy.__oct__() 0 2 1
A Proxy.__add__() 0 2 1
A Proxy.__truediv__() 0 2 1
A Proxy.__str__() 0 2 1

How to fix   Complexity   

Complex Class

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
2
3
from .compat import PY2
4
from .compat import PY3
5
from .compat import with_metaclass
6
from .utils import identity
7
8
9
class _ProxyMethods(object):
10
    # We use properties to override the values of __module__ and
11
    # __doc__. If we add these in ObjectProxy, the derived class
12
    # __dict__ will still be setup to have string variants of these
13
    # attributes and the rules of descriptors means that they appear to
14
    # take precedence over the properties in the base class. To avoid
15
    # that, we copy the properties into the derived class type itself
16
    # via a meta class. In that way the properties will always take
17
    # precedence.
18
19
    @property
20
    def __module__(self):
21
        return self.__wrapped__.__module__
22
23
    @__module__.setter
24
    def __module__(self, value):
25
        self.__wrapped__.__module__ = value
26
27
    @property
28
    def __doc__(self):
29
        return self.__wrapped__.__doc__
30
31
    @__doc__.setter
32
    def __doc__(self, value):
33
        self.__wrapped__.__doc__ = value
34
35
    # We similar use a property for __dict__. We need __dict__ to be
36
    # explicit to ensure that vars() works as expected.
37
38
    @property
39
    def __dict__(self):
40
        return self.__wrapped__.__dict__
41
42
    # Need to also propagate the special __weakref__ attribute for case
43
    # where decorating classes which will define this. If do not define
44
    # it and use a function like inspect.getmembers() on a decorator
45
    # class it will fail. This can't be in the derived classes.
46
47
    @property
48
    def __weakref__(self):
49
        return self.__wrapped__.__weakref__
50
51
52
class _ProxyMetaType(type):
53
    def __new__(cls, name, bases, dictionary):
54
        # Copy our special properties into the class so that they
55
        # always take precedence over attributes of the same name added
56
        # during construction of a derived class. This is to save
57
        # duplicating the implementation for them in all derived classes.
58
59
        dictionary.update(vars(_ProxyMethods))
60
61
        return type.__new__(cls, name, bases, dictionary)
62
63
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