@@ -30,6 +30,10 @@ def class_logger(decorated_cls):
3030 for attr_name , attr_value in decorated_cls .__dict__ .items ():
3131 if callable (attr_value ) and (attr_name not in _excluded_methods ):
3232 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+ )
3337 return decorated_cls
3438
3539
@@ -56,6 +60,35 @@ def wrapper(*args, **kwargs):
5660 return wrapper
5761
5862
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+
5992def add_api_method (api_method_name ):
6093 global _lock
6194 global _api_methods
0 commit comments