#
# Aura Engine (https://gitlab.servus.at/aura/engine)
#
# Copyright (C) 2017-2020 - The Aura Engine Team.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


"""
A collection of Python language utilities.
"""

import inspect
from functools import wraps


def private(member):
    """
    @private Decorator.

    Use this to annotate your methods for private-visibility.

    This is an more expressive alternative to the pythonic underscore visibility.
    """

    @wraps(member)
    def wrapper(*args):
        me = member.__name__
        stack = inspect.stack()
        calling_class = stack[1][0].f_locals["self"].__class__.__name__
        calling_method = stack[1][0].f_code.co_name
        if calling_method not in dir(args[0]) and calling_method is not me:
            msg = f'"{me}(..)" called by "{calling_class}.{calling_method}(..)" is private'
            print(msg)
            raise Exception(msg)
        return member(*args)

    return wrapper