@@ -30,6 +30,10 @@ def class_logger(decorated_cls):
30
30
for attr_name , attr_value in decorated_cls .__dict__ .items ():
31
31
if callable (attr_value ) and (attr_name not in _excluded_methods ):
32
32
setattr (decorated_cls , attr_name , method_logger (attr_value , decorated_cls ))
33
+ elif isinstance (attr_value , property ):
34
+ setattr (
35
+ decorated_cls , attr_name , property_logger (attr_value , decorated_cls )
36
+ )
33
37
return decorated_cls
34
38
35
39
@@ -56,6 +60,35 @@ def wrapper(*args, **kwargs):
56
60
return wrapper
57
61
58
62
63
+ def property_logger (prop , decorated_cls ):
64
+ """Decorator that adds logging functionality to a property."""
65
+
66
+ def shared_wrapper (f ):
67
+ @functools .wraps (f )
68
+ def wrapped (* args , ** kwargs ):
69
+ class_name = decorated_cls .__name__
70
+ property_name = f .__name__
71
+ full_property_name = f"{ class_name .lower ()} -{ property_name .lower ()} "
72
+
73
+ if len (_call_stack ) == 0 :
74
+ add_api_method (full_property_name )
75
+
76
+ _call_stack .append (full_property_name )
77
+ try :
78
+ return f (* args , ** kwargs )
79
+ finally :
80
+ _call_stack .pop ()
81
+
82
+ return wrapped
83
+
84
+ # Apply the wrapper to the getter, setter, and deleter
85
+ return property (
86
+ shared_wrapper (prop .fget ),
87
+ shared_wrapper (prop .fset ) if prop .fset else None ,
88
+ shared_wrapper (prop .fdel ) if prop .fdel else None ,
89
+ )
90
+
91
+
59
92
def add_api_method (api_method_name ):
60
93
global _lock
61
94
global _api_methods
0 commit comments