import functools


def rgetattr(obj, attr: str, safe: bool = False, *args, **kwargs):
    """
    Version récursive de getattr pour utiliser une propriété chaînée même avec None au milieu.
    exemples :
    - rgetattr(obj, 'a.b.c')
    - rgetattr(obj, 'a.b.c', safe=True)

    :param obj: cible
    :type obj: Any

    :param attr: propriété qui peut être chaînée en séparant par '.'
    :type attr: str

    :param safe: indique qu'il faut tester la présence de l'attribut avec hasattr (utile pour les relations entre modèles Django), defaults to False
    :type safe: bool

    :return: valeur de l'attribut
    :rtype: Any
    """
    def _getattr(obj, attr):
        return getattr(obj, attr, *args) if not safe or hasattr(obj, attr) else None
    return functools.reduce(_getattr, [obj] + attr.split('.'))

def safe_rgetattr(obj, attr: str, safe: bool = False, *args, **kwargs):
    """
    version safe de rgetattr
    exemples : safe_rgetattr(obj, 'a.b.c')
    """
    return rgetattr(obj, attr, safe=True, *args, **kwargs)
