# SPDX-License-Identifier: GPLv3-or-later
# Copyright © 2025 pygaindalf Rui Pinheiro
from typing import TYPE_CHECKING, Unpack
from . import lib
from .callable_decorator import CallguardCallableDecorator
if TYPE_CHECKING:
from .types import CallguardOptions
# MARK: Property Decorator
[docs]
class CallguardPropertyDecorator[T: object, **P, R]:
[docs]
def __init__(self, **options: Unpack[CallguardOptions[T, P, R]]) -> None:
self.options = options
def __call__(self, prop: property) -> property:
return self.guard(prop, **self.options)
[docs]
@staticmethod
def guard(method: property, **callguard_options: Unpack[CallguardOptions[T, P, R]]) -> property:
if not lib.callguard_enabled(method):
return method
getter = method.fget
setter = method.fset
deleter = method.fdel
orig_name = callguard_options.get("method_name", method.__name__)
setter_only = callguard_options.get("property_setter_only", False)
if setter_only:
callguarded_getter = getter
else:
callguard_options["method_name"] = f"{orig_name}"
callguarded_getter = CallguardCallableDecorator.guard(getter, **callguard_options) if getter else None
callguard_options["method_name"] = f"{orig_name}.setter"
callguarded_setter = CallguardCallableDecorator.guard(setter, **callguard_options) if setter else None
callguard_options["method_name"] = f"{orig_name}.deleter"
callguarded_deleter = CallguardCallableDecorator.guard(deleter, **callguard_options) if deleter else None
if callguarded_getter is getter and callguarded_setter is setter and callguarded_deleter is deleter:
return method
return property(callguarded_getter, callguarded_setter, callguarded_deleter, method.__doc__)
[docs]
def callguard_property[T: object, **P, R](**callguard_options: Unpack[CallguardOptions[T, P, R]]) -> CallguardPropertyDecorator[T, P, R]:
return CallguardPropertyDecorator(**callguard_options)