1'''For debug purpose we are replacing actual builtin property by the debug property
2'''
3from _pydevd_bundle.pydevd_comm import get_global_debugger
4from _pydevd_bundle.pydevd_constants import DebugInfoHolder, IS_PY2
5import pydevd_tracing
6import traceback
7
8#=======================================================================================================================
9# replace_builtin_property
10#=======================================================================================================================
11def replace_builtin_property(new_property=None):
12    if new_property is None:
13        new_property = DebugProperty
14    original = property
15    if IS_PY2:
16        try:
17            import __builtin__
18            __builtin__.__dict__['property'] = new_property
19        except:
20            if DebugInfoHolder.DEBUG_TRACE_LEVEL:
21                traceback.print_exc() #@Reimport
22    else:
23        try:
24            import builtins #Python 3.0 does not have the __builtin__ module @UnresolvedImport
25            builtins.__dict__['property'] = new_property
26        except:
27            if DebugInfoHolder.DEBUG_TRACE_LEVEL:
28                traceback.print_exc() #@Reimport
29    return original
30
31
32#=======================================================================================================================
33# DebugProperty
34#=======================================================================================================================
35class DebugProperty(object):
36    """A custom property which allows python property to get
37    controlled by the debugger and selectively disable/re-enable
38    the tracing.
39    """
40
41
42    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
43        self.fget = fget
44        self.fset = fset
45        self.fdel = fdel
46        self.__doc__ = doc
47
48
49    def __get__(self, obj, objtype=None):
50        if obj is None:
51            return self
52        global_debugger = get_global_debugger()
53        try:
54            if global_debugger is not None and global_debugger.disable_property_getter_trace:
55                global_debugger.disable_tracing()
56            if self.fget is None:
57                raise AttributeError("unreadable attribute")
58            return self.fget(obj)
59        finally:
60            if global_debugger is not None:
61                global_debugger.enable_tracing()
62
63    def __set__(self, obj, value):
64        global_debugger = get_global_debugger()
65        try:
66            if global_debugger is not None and global_debugger.disable_property_setter_trace:
67                global_debugger.disable_tracing()
68            if self.fset is None:
69                raise AttributeError("can't set attribute")
70            self.fset(obj, value)
71        finally:
72            if global_debugger is not None:
73                global_debugger.enable_tracing()
74
75    def __delete__(self, obj):
76        global_debugger = get_global_debugger()
77        try:
78            if global_debugger is not None and global_debugger.disable_property_deleter_trace:
79                global_debugger.disable_tracing()
80            if self.fdel is None:
81                raise AttributeError("can't delete attribute")
82            self.fdel(obj)
83        finally:
84            if global_debugger is not None:
85                global_debugger.enable_tracing()
86
87    def getter(self, fget):
88        """Overriding getter decorator for the property
89        """
90        self.fget = fget
91        return self
92
93
94    def setter(self, fset):
95        """Overriding setter decorator for the property
96        """
97        self.fset = fset
98        return self
99
100
101    def deleter(self, fdel):
102        """Overriding deleter decorator for the property
103        """
104        self.fdel = fdel
105        return self
106
107