summaryrefslogtreecommitdiff
path: root/python/helpers/pydev/pydevd_traceproperty.py
blob: d8e7e5f9280fd1ec104ec31c808a3504defd9c3a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
'''For debug purpose we are replacing actual builtin property by the debug property
'''
from pydevd_comm import GetGlobalDebugger
from pydevd_constants import * #@UnusedWildImport
import pydevd_tracing

#=======================================================================================================================
# replace_builtin_property
#=======================================================================================================================
def replace_builtin_property(new_property=None):
    if new_property is None:
        new_property = DebugProperty
    original = property
    if not IS_PY3K:
        try:
            import __builtin__
            __builtin__.__dict__['property'] = new_property
        except:
            if DebugInfoHolder.DEBUG_TRACE_LEVEL:
                import traceback;traceback.print_exc() #@Reimport
    else:
        try:
            import builtins #Python 3.0 does not have the __builtin__ module @UnresolvedImport
            builtins.__dict__['property'] = new_property
        except:
            if DebugInfoHolder.DEBUG_TRACE_LEVEL:
                import traceback;traceback.print_exc() #@Reimport
    return original


#=======================================================================================================================
# DebugProperty
#=======================================================================================================================
class DebugProperty(object):
    """A custom property which allows python property to get
    controlled by the debugger and selectively disable/re-enable
    the tracing.
    """


    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
        self.fget = fget
        self.fset = fset
        self.fdel = fdel
        self.__doc__ = doc


    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        global_debugger = GetGlobalDebugger()
        try:
            if global_debugger is not None and global_debugger.disable_property_getter_trace:
                pydevd_tracing.SetTrace(None)
            if self.fget is None:
                raise AttributeError("unreadable attribute")
            return self.fget(obj)
        finally:
            if global_debugger is not None:
                pydevd_tracing.SetTrace(global_debugger.trace_dispatch)


    def __set__(self, obj, value):
        global_debugger = GetGlobalDebugger()
        try:
            if global_debugger is not None and global_debugger.disable_property_setter_trace:
                pydevd_tracing.SetTrace(None)
            if self.fset is None:
                raise AttributeError("can't set attribute")
            self.fset(obj, value)
        finally:
            if global_debugger is not None:
                pydevd_tracing.SetTrace(global_debugger.trace_dispatch)


    def __delete__(self, obj):
        global_debugger = GetGlobalDebugger()
        try:
            if global_debugger is not None and global_debugger.disable_property_deleter_trace:
                pydevd_tracing.SetTrace(None)
            if self.fdel is None:
                raise AttributeError("can't delete attribute")
            self.fdel(obj)
        finally:
            if global_debugger is not None:
                pydevd_tracing.SetTrace(global_debugger.trace_dispatch)


    def getter(self, fget):
        """Overriding getter decorator for the property
        """
        self.fget = fget
        return self


    def setter(self, fset):
        """Overriding setter decorator for the property
        """
        self.fset = fset
        return self


    def deleter(self, fdel):
        """Overriding deleter decorator for the property
        """
        self.fdel = fdel
        return self