1import os
2import sys
3import functools
4import operator
5import weakref
6import inspect
7
8PY2 = sys.version_info[0] == 2
9
10if PY2:
11    string_types = basestring,
12else:
13    string_types = str,
14
15def with_metaclass(meta, *bases):
16    """Create a base class with a metaclass."""
17    return meta("NewBase", bases, {})
18
19class _ObjectProxyMethods(object):
20
21    # We use properties to override the values of __module__ and
22    # __doc__. If we add these in ObjectProxy, the derived class
23    # __dict__ will still be setup to have string variants of these
24    # attributes and the rules of descriptors means that they appear to
25    # take precedence over the properties in the base class. To avoid
26    # that, we copy the properties into the derived class type itself
27    # via a meta class. In that way the properties will always take
28    # precedence.
29
30    @property
31    def __module__(self):
32        return self.__wrapped__.__module__
33
34    @__module__.setter
35    def __module__(self, value):
36        self.__wrapped__.__module__ = value
37
38    @property
39    def __doc__(self):
40        return self.__wrapped__.__doc__
41
42    @__doc__.setter
43    def __doc__(self, value):
44        self.__wrapped__.__doc__ = value
45
46    # We similar use a property for __dict__. We need __dict__ to be
47    # explicit to ensure that vars() works as expected.
48
49    @property
50    def __dict__(self):
51        return self.__wrapped__.__dict__
52
53    # Need to also propagate the special __weakref__ attribute for case
54    # where decorating classes which will define this. If do not define
55    # it and use a function like inspect.getmembers() on a decorator
56    # class it will fail. This can't be in the derived classes.
57
58    @property
59    def __weakref__(self):
60        return self.__wrapped__.__weakref__
61
62class _ObjectProxyMetaType(type):
63    def __new__(cls, name, bases, dictionary):
64        # Copy our special properties into the class so that they
65        # always take precedence over attributes of the same name added
66        # during construction of a derived class. This is to save
67        # duplicating the implementation for them in all derived classes.
68
69        dictionary.update(vars(_ObjectProxyMethods))
70
71        return type.__new__(cls, name, bases, dictionary)
72
73class ObjectProxy(with_metaclass(_ObjectProxyMetaType)):
74
75    __slots__ = '__wrapped__'
76
77    def __init__(self, wrapped):
78        object.__setattr__(self, '__wrapped__', wrapped)
79
80        # Python 3.2+ has the __qualname__ attribute, but it does not
81        # allow it to be overridden using a property and it must instead
82        # be an actual string object instead.
83
84        try:
85            object.__setattr__(self, '__qualname__', wrapped.__qualname__)
86        except AttributeError:
87            pass
88
89        # Python 3.10 onwards also does not allow itself to be overridden
90        # using a properly and it must instead be set explicitly.
91
92        try:
93            object.__setattr__(self, '__annotations__', wrapped.__annotations__)
94        except AttributeError:
95            pass
96
97    @property
98    def __name__(self):
99        return self.__wrapped__.__name__
100
101    @__name__.setter
102    def __name__(self, value):
103        self.__wrapped__.__name__ = value
104
105    @property
106    def __class__(self):
107        return self.__wrapped__.__class__
108
109    @__class__.setter
110    def __class__(self, value):
111        self.__wrapped__.__class__ = value
112
113    def __dir__(self):
114        return dir(self.__wrapped__)
115
116    def __str__(self):
117        return str(self.__wrapped__)
118
119    if not PY2:
120        def __bytes__(self):
121            return bytes(self.__wrapped__)
122
123    def __repr__(self):
124        return '<{} at 0x{:x} for {} at 0x{:x}>'.format(
125                type(self).__name__, id(self),
126                type(self.__wrapped__).__name__,
127                id(self.__wrapped__))
128
129    def __reversed__(self):
130        return reversed(self.__wrapped__)
131
132    if not PY2:
133        def __round__(self):
134            return round(self.__wrapped__)
135
136    if sys.hexversion >= 0x03070000:
137        def __mro_entries__(self, bases):
138            return (self.__wrapped__,)
139
140    def __lt__(self, other):
141        return self.__wrapped__ < other
142
143    def __le__(self, other):
144        return self.__wrapped__ <= other
145
146    def __eq__(self, other):
147        return self.__wrapped__ == other
148
149    def __ne__(self, other):
150        return self.__wrapped__ != other
151
152    def __gt__(self, other):
153        return self.__wrapped__ > other
154
155    def __ge__(self, other):
156        return self.__wrapped__ >= other
157
158    def __hash__(self):
159        return hash(self.__wrapped__)
160
161    def __nonzero__(self):
162        return bool(self.__wrapped__)
163
164    def __bool__(self):
165        return bool(self.__wrapped__)
166
167    def __setattr__(self, name, value):
168        if name.startswith('_self_'):
169            object.__setattr__(self, name, value)
170
171        elif name == '__wrapped__':
172            object.__setattr__(self, name, value)
173            try:
174                object.__delattr__(self, '__qualname__')
175            except AttributeError:
176                pass
177            try:
178                object.__setattr__(self, '__qualname__', value.__qualname__)
179            except AttributeError:
180                pass
181            try:
182                object.__delattr__(self, '__annotations__')
183            except AttributeError:
184                pass
185            try:
186                object.__setattr__(self, '__annotations__', value.__annotations__)
187            except AttributeError:
188                pass
189
190        elif name == '__qualname__':
191            setattr(self.__wrapped__, name, value)
192            object.__setattr__(self, name, value)
193
194        elif name == '__annotations__':
195            setattr(self.__wrapped__, name, value)
196            object.__setattr__(self, name, value)
197
198        elif hasattr(type(self), name):
199            object.__setattr__(self, name, value)
200
201        else:
202            setattr(self.__wrapped__, name, value)
203
204    def __getattr__(self, name):
205        # If we are being to lookup '__wrapped__' then the
206        # '__init__()' method cannot have been called.
207
208        if name == '__wrapped__':
209            raise ValueError('wrapper has not been initialised')
210
211        return getattr(self.__wrapped__, name)
212
213    def __delattr__(self, name):
214        if name.startswith('_self_'):
215            object.__delattr__(self, name)
216
217        elif name == '__wrapped__':
218            raise TypeError('__wrapped__ must be an object')
219
220        elif name == '__qualname__':
221            object.__delattr__(self, name)
222            delattr(self.__wrapped__, name)
223
224        elif hasattr(type(self), name):
225            object.__delattr__(self, name)
226
227        else:
228            delattr(self.__wrapped__, name)
229
230    def __add__(self, other):
231        return self.__wrapped__ + other
232
233    def __sub__(self, other):
234        return self.__wrapped__ - other
235
236    def __mul__(self, other):
237        return self.__wrapped__ * other
238
239    def __div__(self, other):
240        return operator.div(self.__wrapped__, other)
241
242    def __truediv__(self, other):
243        return operator.truediv(self.__wrapped__, other)
244
245    def __floordiv__(self, other):
246        return self.__wrapped__ // other
247
248    def __mod__(self, other):
249        return self.__wrapped__ % other
250
251    def __divmod__(self, other):
252        return divmod(self.__wrapped__, other)
253
254    def __pow__(self, other, *args):
255        return pow(self.__wrapped__, other, *args)
256
257    def __lshift__(self, other):
258        return self.__wrapped__ << other
259
260    def __rshift__(self, other):
261        return self.__wrapped__ >> other
262
263    def __and__(self, other):
264        return self.__wrapped__ & other
265
266    def __xor__(self, other):
267        return self.__wrapped__ ^ other
268
269    def __or__(self, other):
270        return self.__wrapped__ | other
271
272    def __radd__(self, other):
273        return other + self.__wrapped__
274
275    def __rsub__(self, other):
276        return other - self.__wrapped__
277
278    def __rmul__(self, other):
279        return other * self.__wrapped__
280
281    def __rdiv__(self, other):
282        return operator.div(other, self.__wrapped__)
283
284    def __rtruediv__(self, other):
285        return operator.truediv(other, self.__wrapped__)
286
287    def __rfloordiv__(self, other):
288        return other // self.__wrapped__
289
290    def __rmod__(self, other):
291        return other % self.__wrapped__
292
293    def __rdivmod__(self, other):
294        return divmod(other, self.__wrapped__)
295
296    def __rpow__(self, other, *args):
297        return pow(other, self.__wrapped__, *args)
298
299    def __rlshift__(self, other):
300        return other << self.__wrapped__
301
302    def __rrshift__(self, other):
303        return other >> self.__wrapped__
304
305    def __rand__(self, other):
306        return other & self.__wrapped__
307
308    def __rxor__(self, other):
309        return other ^ self.__wrapped__
310
311    def __ror__(self, other):
312        return other | self.__wrapped__
313
314    def __iadd__(self, other):
315        self.__wrapped__ += other
316        return self
317
318    def __isub__(self, other):
319        self.__wrapped__ -= other
320        return self
321
322    def __imul__(self, other):
323        self.__wrapped__ *= other
324        return self
325
326    def __idiv__(self, other):
327        self.__wrapped__ = operator.idiv(self.__wrapped__, other)
328        return self
329
330    def __itruediv__(self, other):
331        self.__wrapped__ = operator.itruediv(self.__wrapped__, other)
332        return self
333
334    def __ifloordiv__(self, other):
335        self.__wrapped__ //= other
336        return self
337
338    def __imod__(self, other):
339        self.__wrapped__ %= other
340        return self
341
342    def __ipow__(self, other):
343        self.__wrapped__ **= other
344        return self
345
346    def __ilshift__(self, other):
347        self.__wrapped__ <<= other
348        return self
349
350    def __irshift__(self, other):
351        self.__wrapped__ >>= other
352        return self
353
354    def __iand__(self, other):
355        self.__wrapped__ &= other
356        return self
357
358    def __ixor__(self, other):
359        self.__wrapped__ ^= other
360        return self
361
362    def __ior__(self, other):
363        self.__wrapped__ |= other
364        return self
365
366    def __neg__(self):
367        return -self.__wrapped__
368
369    def __pos__(self):
370        return +self.__wrapped__
371
372    def __abs__(self):
373        return abs(self.__wrapped__)
374
375    def __invert__(self):
376        return ~self.__wrapped__
377
378    def __int__(self):
379        return int(self.__wrapped__)
380
381    def __long__(self):
382        return long(self.__wrapped__)
383
384    def __float__(self):
385        return float(self.__wrapped__)
386
387    def __complex__(self):
388        return complex(self.__wrapped__)
389
390    def __oct__(self):
391        return oct(self.__wrapped__)
392
393    def __hex__(self):
394        return hex(self.__wrapped__)
395
396    def __index__(self):
397        return operator.index(self.__wrapped__)
398
399    def __len__(self):
400        return len(self.__wrapped__)
401
402    def __contains__(self, value):
403        return value in self.__wrapped__
404
405    def __getitem__(self, key):
406        return self.__wrapped__[key]
407
408    def __setitem__(self, key, value):
409        self.__wrapped__[key] = value
410
411    def __delitem__(self, key):
412        del self.__wrapped__[key]
413
414    def __getslice__(self, i, j):
415        return self.__wrapped__[i:j]
416
417    def __setslice__(self, i, j, value):
418        self.__wrapped__[i:j] = value
419
420    def __delslice__(self, i, j):
421        del self.__wrapped__[i:j]
422
423    def __enter__(self):
424        return self.__wrapped__.__enter__()
425
426    def __exit__(self, *args, **kwargs):
427        return self.__wrapped__.__exit__(*args, **kwargs)
428
429    def __iter__(self):
430        return iter(self.__wrapped__)
431
432    def __copy__(self):
433        raise NotImplementedError('object proxy must define __copy__()')
434
435    def __deepcopy__(self, memo):
436        raise NotImplementedError('object proxy must define __deepcopy__()')
437
438    def __reduce__(self):
439        raise NotImplementedError(
440                'object proxy must define __reduce_ex__()')
441
442    def __reduce_ex__(self, protocol):
443        raise NotImplementedError(
444                'object proxy must define __reduce_ex__()')
445
446class CallableObjectProxy(ObjectProxy):
447
448    def __call__(self, *args, **kwargs):
449        return self.__wrapped__(*args, **kwargs)
450
451class PartialCallableObjectProxy(ObjectProxy):
452
453    def __init__(self, *args, **kwargs):
454        if len(args) < 1:
455            raise TypeError('partial type takes at least one argument')
456
457        wrapped, args = args[0], args[1:]
458
459        if not callable(wrapped):
460            raise TypeError('the first argument must be callable')
461
462        super(PartialCallableObjectProxy, self).__init__(wrapped)
463
464        self._self_args = args
465        self._self_kwargs = kwargs
466
467    def __call__(self, *args, **kwargs):
468        _args = self._self_args + args
469
470        _kwargs = dict(self._self_kwargs)
471        _kwargs.update(kwargs)
472
473        return self.__wrapped__(*_args, **_kwargs)
474
475class _FunctionWrapperBase(ObjectProxy):
476
477    __slots__ = ('_self_instance', '_self_wrapper', '_self_enabled',
478            '_self_binding', '_self_parent')
479
480    def __init__(self, wrapped, instance, wrapper, enabled=None,
481            binding='function', parent=None):
482
483        super(_FunctionWrapperBase, self).__init__(wrapped)
484
485        object.__setattr__(self, '_self_instance', instance)
486        object.__setattr__(self, '_self_wrapper', wrapper)
487        object.__setattr__(self, '_self_enabled', enabled)
488        object.__setattr__(self, '_self_binding', binding)
489        object.__setattr__(self, '_self_parent', parent)
490
491    def __get__(self, instance, owner):
492        # This method is actually doing double duty for both unbound and
493        # bound derived wrapper classes. It should possibly be broken up
494        # and the distinct functionality moved into the derived classes.
495        # Can't do that straight away due to some legacy code which is
496        # relying on it being here in this base class.
497        #
498        # The distinguishing attribute which determines whether we are
499        # being called in an unbound or bound wrapper is the parent
500        # attribute. If binding has never occurred, then the parent will
501        # be None.
502        #
503        # First therefore, is if we are called in an unbound wrapper. In
504        # this case we perform the binding.
505        #
506        # We have one special case to worry about here. This is where we
507        # are decorating a nested class. In this case the wrapped class
508        # would not have a __get__() method to call. In that case we
509        # simply return self.
510        #
511        # Note that we otherwise still do binding even if instance is
512        # None and accessing an unbound instance method from a class.
513        # This is because we need to be able to later detect that
514        # specific case as we will need to extract the instance from the
515        # first argument of those passed in.
516
517        if self._self_parent is None:
518            if not inspect.isclass(self.__wrapped__):
519                descriptor = self.__wrapped__.__get__(instance, owner)
520
521                return self.__bound_function_wrapper__(descriptor, instance,
522                        self._self_wrapper, self._self_enabled,
523                        self._self_binding, self)
524
525            return self
526
527        # Now we have the case of binding occurring a second time on what
528        # was already a bound function. In this case we would usually
529        # return ourselves again. This mirrors what Python does.
530        #
531        # The special case this time is where we were originally bound
532        # with an instance of None and we were likely an instance
533        # method. In that case we rebind against the original wrapped
534        # function from the parent again.
535
536        if self._self_instance is None and self._self_binding == 'function':
537            descriptor = self._self_parent.__wrapped__.__get__(
538                    instance, owner)
539
540            return self._self_parent.__bound_function_wrapper__(
541                    descriptor, instance, self._self_wrapper,
542                    self._self_enabled, self._self_binding,
543                    self._self_parent)
544
545        return self
546
547    def __call__(self, *args, **kwargs):
548        # If enabled has been specified, then evaluate it at this point
549        # and if the wrapper is not to be executed, then simply return
550        # the bound function rather than a bound wrapper for the bound
551        # function. When evaluating enabled, if it is callable we call
552        # it, otherwise we evaluate it as a boolean.
553
554        if self._self_enabled is not None:
555            if callable(self._self_enabled):
556                if not self._self_enabled():
557                    return self.__wrapped__(*args, **kwargs)
558            elif not self._self_enabled:
559                return self.__wrapped__(*args, **kwargs)
560
561        # This can occur where initial function wrapper was applied to
562        # a function that was already bound to an instance. In that case
563        # we want to extract the instance from the function and use it.
564
565        if self._self_binding in ('function', 'classmethod'):
566            if self._self_instance is None:
567                instance = getattr(self.__wrapped__, '__self__', None)
568                if instance is not None:
569                    return self._self_wrapper(self.__wrapped__, instance,
570                            args, kwargs)
571
572        # This is generally invoked when the wrapped function is being
573        # called as a normal function and is not bound to a class as an
574        # instance method. This is also invoked in the case where the
575        # wrapped function was a method, but this wrapper was in turn
576        # wrapped using the staticmethod decorator.
577
578        return self._self_wrapper(self.__wrapped__, self._self_instance,
579                args, kwargs)
580
581    def __set_name__(self, owner, name):
582        # This is a special method use to supply information to
583        # descriptors about what the name of variable in a class
584        # definition is. Not wanting to add this to ObjectProxy as not
585        # sure of broader implications of doing that. Thus restrict to
586        # FunctionWrapper used by decorators.
587
588        if hasattr(self.__wrapped__, "__set_name__"):
589            self.__wrapped__.__set_name__(owner, name)
590
591    def __subclasscheck__(self, subclass):
592        # This is a special method used by issubclass() to make checks
593        # about inheritance of classes. We need to upwrap any object
594        # proxy. Not wanting to add this to ObjectProxy as not sure of
595        # broader implications of doing that. Thus restrict to
596        # FunctionWrapper used by decorators.
597
598        if hasattr(subclass, "__wrapped__"):
599            return issubclass(subclass.__wrapped__, self.__wrapped__)
600        else:
601            return issubclass(subclass, self.__wrapped__)
602
603class BoundFunctionWrapper(_FunctionWrapperBase):
604
605    def __call__(self, *args, **kwargs):
606        # If enabled has been specified, then evaluate it at this point
607        # and if the wrapper is not to be executed, then simply return
608        # the bound function rather than a bound wrapper for the bound
609        # function. When evaluating enabled, if it is callable we call
610        # it, otherwise we evaluate it as a boolean.
611
612        if self._self_enabled is not None:
613            if callable(self._self_enabled):
614                if not self._self_enabled():
615                    return self.__wrapped__(*args, **kwargs)
616            elif not self._self_enabled:
617                return self.__wrapped__(*args, **kwargs)
618
619        # We need to do things different depending on whether we are
620        # likely wrapping an instance method vs a static method or class
621        # method.
622
623        if self._self_binding == 'function':
624            if self._self_instance is None:
625                # This situation can occur where someone is calling the
626                # instancemethod via the class type and passing the instance
627                # as the first argument. We need to shift the args before
628                # making the call to the wrapper and effectively bind the
629                # instance to the wrapped function using a partial so the
630                # wrapper doesn't see anything as being different.
631
632                if not args:
633                    raise TypeError('missing 1 required positional argument')
634
635                instance, args = args[0], args[1:]
636                wrapped = PartialCallableObjectProxy(self.__wrapped__, instance)
637                return self._self_wrapper(wrapped, instance, args, kwargs)
638
639            return self._self_wrapper(self.__wrapped__, self._self_instance,
640                    args, kwargs)
641
642        else:
643            # As in this case we would be dealing with a classmethod or
644            # staticmethod, then _self_instance will only tell us whether
645            # when calling the classmethod or staticmethod they did it via an
646            # instance of the class it is bound to and not the case where
647            # done by the class type itself. We thus ignore _self_instance
648            # and use the __self__ attribute of the bound function instead.
649            # For a classmethod, this means instance will be the class type
650            # and for a staticmethod it will be None. This is probably the
651            # more useful thing we can pass through even though we loose
652            # knowledge of whether they were called on the instance vs the
653            # class type, as it reflects what they have available in the
654            # decoratored function.
655
656            instance = getattr(self.__wrapped__, '__self__', None)
657
658            return self._self_wrapper(self.__wrapped__, instance, args,
659                    kwargs)
660
661class FunctionWrapper(_FunctionWrapperBase):
662
663    __bound_function_wrapper__ = BoundFunctionWrapper
664
665    def __init__(self, wrapped, wrapper, enabled=None):
666        # What it is we are wrapping here could be anything. We need to
667        # try and detect specific cases though. In particular, we need
668        # to detect when we are given something that is a method of a
669        # class. Further, we need to know when it is likely an instance
670        # method, as opposed to a class or static method. This can
671        # become problematic though as there isn't strictly a fool proof
672        # method of knowing.
673        #
674        # The situations we could encounter when wrapping a method are:
675        #
676        # 1. The wrapper is being applied as part of a decorator which
677        # is a part of the class definition. In this case what we are
678        # given is the raw unbound function, classmethod or staticmethod
679        # wrapper objects.
680        #
681        # The problem here is that we will not know we are being applied
682        # in the context of the class being set up. This becomes
683        # important later for the case of an instance method, because in
684        # that case we just see it as a raw function and can't
685        # distinguish it from wrapping a normal function outside of
686        # a class context.
687        #
688        # 2. The wrapper is being applied when performing monkey
689        # patching of the class type afterwards and the method to be
690        # wrapped was retrieved direct from the __dict__ of the class
691        # type. This is effectively the same as (1) above.
692        #
693        # 3. The wrapper is being applied when performing monkey
694        # patching of the class type afterwards and the method to be
695        # wrapped was retrieved from the class type. In this case
696        # binding will have been performed where the instance against
697        # which the method is bound will be None at that point.
698        #
699        # This case is a problem because we can no longer tell if the
700        # method was a static method, plus if using Python3, we cannot
701        # tell if it was an instance method as the concept of an
702        # unnbound method no longer exists.
703        #
704        # 4. The wrapper is being applied when performing monkey
705        # patching of an instance of a class. In this case binding will
706        # have been perfomed where the instance was not None.
707        #
708        # This case is a problem because we can no longer tell if the
709        # method was a static method.
710        #
711        # Overall, the best we can do is look at the original type of the
712        # object which was wrapped prior to any binding being done and
713        # see if it is an instance of classmethod or staticmethod. In
714        # the case where other decorators are between us and them, if
715        # they do not propagate the __class__  attribute so that the
716        # isinstance() checks works, then likely this will do the wrong
717        # thing where classmethod and staticmethod are used.
718        #
719        # Since it is likely to be very rare that anyone even puts
720        # decorators around classmethod and staticmethod, likelihood of
721        # that being an issue is very small, so we accept it and suggest
722        # that those other decorators be fixed. It is also only an issue
723        # if a decorator wants to actually do things with the arguments.
724        #
725        # As to not being able to identify static methods properly, we
726        # just hope that that isn't something people are going to want
727        # to wrap, or if they do suggest they do it the correct way by
728        # ensuring that it is decorated in the class definition itself,
729        # or patch it in the __dict__ of the class type.
730        #
731        # So to get the best outcome we can, whenever we aren't sure what
732        # it is, we label it as a 'function'. If it was already bound and
733        # that is rebound later, we assume that it will be an instance
734        # method and try an cope with the possibility that the 'self'
735        # argument it being passed as an explicit argument and shuffle
736        # the arguments around to extract 'self' for use as the instance.
737
738        if isinstance(wrapped, classmethod):
739            binding = 'classmethod'
740
741        elif isinstance(wrapped, staticmethod):
742            binding = 'staticmethod'
743
744        elif hasattr(wrapped, '__self__'):
745            if inspect.isclass(wrapped.__self__):
746                binding = 'classmethod'
747            else:
748                binding = 'function'
749
750        else:
751            binding = 'function'
752
753        super(FunctionWrapper, self).__init__(wrapped, None, wrapper,
754                enabled, binding)
755
756try:
757    if not os.environ.get('WRAPT_DISABLE_EXTENSIONS'):
758        from ._wrappers import (ObjectProxy, CallableObjectProxy,
759            PartialCallableObjectProxy, FunctionWrapper,
760            BoundFunctionWrapper, _FunctionWrapperBase)
761except ImportError:
762    pass
763
764# Helper functions for applying wrappers to existing functions.
765
766def resolve_path(module, name):
767    if isinstance(module, string_types):
768        __import__(module)
769        module = sys.modules[module]
770
771    parent = module
772
773    path = name.split('.')
774    attribute = path[0]
775
776    # We can't just always use getattr() because in doing
777    # that on a class it will cause binding to occur which
778    # will complicate things later and cause some things not
779    # to work. For the case of a class we therefore access
780    # the __dict__ directly. To cope though with the wrong
781    # class being given to us, or a method being moved into
782    # a base class, we need to walk the class hierarchy to
783    # work out exactly which __dict__ the method was defined
784    # in, as accessing it from __dict__ will fail if it was
785    # not actually on the class given. Fallback to using
786    # getattr() if we can't find it. If it truly doesn't
787    # exist, then that will fail.
788
789    def lookup_attribute(parent, attribute):
790        if inspect.isclass(parent):
791            for cls in inspect.getmro(parent):
792                if attribute in vars(cls):
793                    return vars(cls)[attribute]
794            else:
795                return getattr(parent, attribute)
796        else:
797            return getattr(parent, attribute)
798
799    original = lookup_attribute(parent, attribute)
800
801    for attribute in path[1:]:
802        parent = original
803        original = lookup_attribute(parent, attribute)
804
805    return (parent, attribute, original)
806
807def apply_patch(parent, attribute, replacement):
808    setattr(parent, attribute, replacement)
809
810def wrap_object(module, name, factory, args=(), kwargs={}):
811    (parent, attribute, original) = resolve_path(module, name)
812    wrapper = factory(original, *args, **kwargs)
813    apply_patch(parent, attribute, wrapper)
814    return wrapper
815
816# Function for applying a proxy object to an attribute of a class
817# instance. The wrapper works by defining an attribute of the same name
818# on the class which is a descriptor and which intercepts access to the
819# instance attribute. Note that this cannot be used on attributes which
820# are themselves defined by a property object.
821
822class AttributeWrapper(object):
823
824    def __init__(self, attribute, factory, args, kwargs):
825        self.attribute = attribute
826        self.factory = factory
827        self.args = args
828        self.kwargs = kwargs
829
830    def __get__(self, instance, owner):
831        value = instance.__dict__[self.attribute]
832        return self.factory(value, *self.args, **self.kwargs)
833
834    def __set__(self, instance, value):
835        instance.__dict__[self.attribute] = value
836
837    def __delete__(self, instance):
838        del instance.__dict__[self.attribute]
839
840def wrap_object_attribute(module, name, factory, args=(), kwargs={}):
841    path, attribute = name.rsplit('.', 1)
842    parent = resolve_path(module, path)[2]
843    wrapper = AttributeWrapper(attribute, factory, args, kwargs)
844    apply_patch(parent, attribute, wrapper)
845    return wrapper
846
847# Functions for creating a simple decorator using a FunctionWrapper,
848# plus short cut functions for applying wrappers to functions. These are
849# for use when doing monkey patching. For a more featured way of
850# creating decorators see the decorator decorator instead.
851
852def function_wrapper(wrapper):
853    def _wrapper(wrapped, instance, args, kwargs):
854        target_wrapped = args[0]
855        if instance is None:
856            target_wrapper = wrapper
857        elif inspect.isclass(instance):
858            target_wrapper = wrapper.__get__(None, instance)
859        else:
860            target_wrapper = wrapper.__get__(instance, type(instance))
861        return FunctionWrapper(target_wrapped, target_wrapper)
862    return FunctionWrapper(wrapper, _wrapper)
863
864def wrap_function_wrapper(module, name, wrapper):
865    return wrap_object(module, name, FunctionWrapper, (wrapper,))
866
867def patch_function_wrapper(module, name):
868    def _wrapper(wrapper):
869        return wrap_object(module, name, FunctionWrapper, (wrapper,))
870    return _wrapper
871
872def transient_function_wrapper(module, name):
873    def _decorator(wrapper):
874        def _wrapper(wrapped, instance, args, kwargs):
875            target_wrapped = args[0]
876            if instance is None:
877                target_wrapper = wrapper
878            elif inspect.isclass(instance):
879                target_wrapper = wrapper.__get__(None, instance)
880            else:
881                target_wrapper = wrapper.__get__(instance, type(instance))
882            def _execute(wrapped, instance, args, kwargs):
883                (parent, attribute, original) = resolve_path(module, name)
884                replacement = FunctionWrapper(original, target_wrapper)
885                setattr(parent, attribute, replacement)
886                try:
887                    return wrapped(*args, **kwargs)
888                finally:
889                    setattr(parent, attribute, original)
890            return FunctionWrapper(target_wrapped, _execute)
891        return FunctionWrapper(wrapper, _wrapper)
892    return _decorator
893
894# A weak function proxy. This will work on instance methods, class
895# methods, static methods and regular functions. Special treatment is
896# needed for the method types because the bound method is effectively a
897# transient object and applying a weak reference to one will immediately
898# result in it being destroyed and the weakref callback called. The weak
899# reference is therefore applied to the instance the method is bound to
900# and the original function. The function is then rebound at the point
901# of a call via the weak function proxy.
902
903def _weak_function_proxy_callback(ref, proxy, callback):
904    if proxy._self_expired:
905        return
906
907    proxy._self_expired = True
908
909    # This could raise an exception. We let it propagate back and let
910    # the weakref.proxy() deal with it, at which point it generally
911    # prints out a short error message direct to stderr and keeps going.
912
913    if callback is not None:
914        callback(proxy)
915
916class WeakFunctionProxy(ObjectProxy):
917
918    __slots__ = ('_self_expired', '_self_instance')
919
920    def __init__(self, wrapped, callback=None):
921        # We need to determine if the wrapped function is actually a
922        # bound method. In the case of a bound method, we need to keep a
923        # reference to the original unbound function and the instance.
924        # This is necessary because if we hold a reference to the bound
925        # function, it will be the only reference and given it is a
926        # temporary object, it will almost immediately expire and
927        # the weakref callback triggered. So what is done is that we
928        # hold a reference to the instance and unbound function and
929        # when called bind the function to the instance once again and
930        # then call it. Note that we avoid using a nested function for
931        # the callback here so as not to cause any odd reference cycles.
932
933        _callback = callback and functools.partial(
934                _weak_function_proxy_callback, proxy=self,
935                callback=callback)
936
937        self._self_expired = False
938
939        if isinstance(wrapped, _FunctionWrapperBase):
940            self._self_instance = weakref.ref(wrapped._self_instance,
941                    _callback)
942
943            if wrapped._self_parent is not None:
944                super(WeakFunctionProxy, self).__init__(
945                        weakref.proxy(wrapped._self_parent, _callback))
946
947            else:
948                super(WeakFunctionProxy, self).__init__(
949                        weakref.proxy(wrapped, _callback))
950
951            return
952
953        try:
954            self._self_instance = weakref.ref(wrapped.__self__, _callback)
955
956            super(WeakFunctionProxy, self).__init__(
957                    weakref.proxy(wrapped.__func__, _callback))
958
959        except AttributeError:
960            self._self_instance = None
961
962            super(WeakFunctionProxy, self).__init__(
963                    weakref.proxy(wrapped, _callback))
964
965    def __call__(self, *args, **kwargs):
966        # We perform a boolean check here on the instance and wrapped
967        # function as that will trigger the reference error prior to
968        # calling if the reference had expired.
969
970        instance = self._self_instance and self._self_instance()
971        function = self.__wrapped__ and self.__wrapped__
972
973        # If the wrapped function was originally a bound function, for
974        # which we retained a reference to the instance and the unbound
975        # function we need to rebind the function and then call it. If
976        # not just called the wrapped function.
977
978        if instance is None:
979            return self.__wrapped__(*args, **kwargs)
980
981        return function.__get__(instance, type(instance))(*args, **kwargs)
982