# Path: robot_designer_plugin/core/config.py
# PLUGIN_PREFIX = "robotdesigner"
# 
# EXCEPTION_MESSAGE = "\tException:\t%s\n\tMessages:\n\t\t%s\n%s\n%s"
# 
# Path: robot_designer_plugin/core/logfile.py
# def LogFunction(func):
#     def func_logger(self, context):
# def log_callstack(back_trace=False):
# def log_callstack_last(back_trace=False):
# 
# Path: robot_designer_plugin/core/conditions.py
# class Condition(object):
#     """
#     Base Class for conditions.
# 
#     Classes should implement a ``check()`` method which returns a tuple of (bool,str) stating whether
#     the condition's are met and an (potentially) empty error message.
# 
#     Using the :meth:`.operators.RDOperator.Preconditions` decorator, the conditions that should be met
#     when executing an operator (i.e., a subclass of :class:`.operators.RDOperator`) are added to the classes'
#     list of preconditions and :meth:`check_conditions` is called when Blender executes the
#     :meth:`.operators.RDOperator.poll` method.
# 
#     .. note::
# 
#         Instances of this type should never be created.
# 
#     For examples see :class:`robot_designer_plugin.operators.helpers.ModelSelected`.
#     """
# 
#     @staticmethod
#     def check_conditions(*conditions):
#         """
#         Checks whether the arguments are met.
# 
#         :param conditions: A an arbitrary number of conditions
#         :type conditions: :class:`Condition` sub classes.
#         :return: Tuple(bool, str), True and empty string if all conditions are met. False and sting with message of
#         unmet conditions.
#         """
#         try:
#             check = [i.check() for i in conditions]
#             return all([i[0] for i in check]), "\n".join([i[1] for i in check if not i[0]])
# 
#         except Exception as e:
#             logger.error("Exception in check precondition!\n {} \nConditions: {}  {} {}".format(EXCEPTION_MESSAGE,
#                          type(e).__name__, e, log_callstack(), log_callstack(True), conditions))
#             return False, "Exception raised"
# 
#     @staticmethod
#     def call():
#         '''
#         Needs to be overridden in sub classes
# 
#         :raises: NotImplementedError
#         '''
#         raise NotImplementedError("Must be overridden in subclasses")
# 
# Path: robot_designer_plugin/core/gui.py
# class InfoBox(object):
#     """
#     This class collects messages (e.g., from :meth:`.operators.operators.RDOperator.poll`) and displays them
#     with an info, either in a separated box or the current layout.
# 
#     See :ref:`gui_development` for an example.
#     """
# 
#     global_messages = []
# 
#     def __init__(self, layout):
#         """
#         Constructor.
# 
#         :param layout: Blender gui element as passed to the
#             :meth:`robot_designer_plugin.interface.main.UserInterface.draw` method.
#         """
#         self.messages = []
#         self.layout = layout
# 
#     def add_message(self, message):
#         """
#         Adds a string message to the info box.
# 
#         :param message: message
#         :type message: str
#         """
#         self.messages.append(message)
# 
#     def draw_info(self, additional_messages=[], icon=StringConstants.info):
#         """
#         Draws the info box onto the layout.
# 
#         :param additional_messages: Additional messages can be appended.
#         """
#         messages = self.messages + additional_messages
#         if messages:
# 
#             column = self.layout.column(align=True)
#             for text in set(messages):
#                 column.label(text=text, icon=icon)
# 
#     @classmethod
#     def draw_global_info(cls, layout):
# 
#         if cls.global_messages:
#             ib = InfoBox(layout)
#             ib.draw_info(additional_messages=cls.global_messages, icon=StringConstants.error)


import inspect
import bpy
from .config import PLUGIN_PREFIX, EXCEPTION_MESSAGE
from .logfile import log_callstack, log_callstack_last, operator_logger as logger
from .conditions import Condition
from .gui import InfoBox

        bpy.ops.plugin_name.newop(test="Hello World)


    This example show an operator that opens a window containing the message *"Hello World"*. While this is feasible
    for smaller plugins, what happens, if you have a lot of operators written, and you want to have code completion.
    What happens if you want to refactor the names of of the identifier or class attributes. While for the latter there
    is no simple solution available, the :mod:`robot_designer_plugin.core` provides this wrapper class with
    an additional ``run(**kwargs)`` method (that can---and should---be overridden to provide keyword completion).
    Furthermore, it provides decorators for automatically setting preconditions (that define the
    :meth:`bpy.types.Operator.poll` method) for automatic condition checking, logging functionality and post condition
    checking. Together with the :meth:`.pluginmanager.PluginManager.register` method, this makes developing faster (
    code completion,
    code navigation, less verbosity, ...) and safer.

    An examplary :term:`operator` looks like this:

    .. literalinclude:: ../../../resources/templates/operator.py
        :emphasize-lines: 7-11,16-18, 31-33, 60-62
        :lines: 50-111
        :linenos:

    A template is located in ``<RobotDesignerDirectory>/resources/templates/operator.py`` (where you should insert
    the path to the repository) that can be used to quickly write new operators.
    """

    _pre_conditions = {}
    """Dictionary set by the :meth:`PreConditions` decorator. Stores the :class:`.conditions.Condition` that are
    checked for each :class:`RDOperator` -based operator"""


# Path: robot_designer_plugin/core/config.py
# PLUGIN_PREFIX = "robotdesigner"
# 
# EXCEPTION_MESSAGE = "\tException:\t%s\n\tMessages:\n\t\t%s\n%s\n%s"
# 
# Path: robot_designer_plugin/core/logfile.py
# def LogFunction(func):
#     def func_logger(self, context):
# def log_callstack(back_trace=False):
# def log_callstack_last(back_trace=False):
# 
# Path: robot_designer_plugin/core/conditions.py
# class Condition(object):
#     """
#     Base Class for conditions.
# 
#     Classes should implement a ``check()`` method which returns a tuple of (bool,str) stating whether
#     the condition's are met and an (potentially) empty error message.
# 
#     Using the :meth:`.operators.RDOperator.Preconditions` decorator, the conditions that should be met
#     when executing an operator (i.e., a subclass of :class:`.operators.RDOperator`) are added to the classes'
#     list of preconditions and :meth:`check_conditions` is called when Blender executes the
#     :meth:`.operators.RDOperator.poll` method.
# 
#     .. note::
# 
#         Instances of this type should never be created.
# 
#     For examples see :class:`robot_designer_plugin.operators.helpers.ModelSelected`.
#     """
# 
#     @staticmethod
#     def check_conditions(*conditions):
#         """
#         Checks whether the arguments are met.
# 
#         :param conditions: A an arbitrary number of conditions
#         :type conditions: :class:`Condition` sub classes.
#         :return: Tuple(bool, str), True and empty string if all conditions are met. False and sting with message of
#         unmet conditions.
#         """
#         try:
#             check = [i.check() for i in conditions]
#             return all([i[0] for i in check]), "\n".join([i[1] for i in check if not i[0]])
# 
#         except Exception as e:
#             logger.error("Exception in check precondition!\n {} \nConditions: {}  {} {}".format(EXCEPTION_MESSAGE,
#                          type(e).__name__, e, log_callstack(), log_callstack(True), conditions))
#             return False, "Exception raised"
# 
#     @staticmethod
#     def call():
#         '''
#         Needs to be overridden in sub classes
# 
#         :raises: NotImplementedError
#         '''
#         raise NotImplementedError("Must be overridden in subclasses")
# 
# Path: robot_designer_plugin/core/gui.py
# class InfoBox(object):
#     """
#     This class collects messages (e.g., from :meth:`.operators.operators.RDOperator.poll`) and displays them
#     with an info, either in a separated box or the current layout.
# 
#     See :ref:`gui_development` for an example.
#     """
# 
#     global_messages = []
# 
#     def __init__(self, layout):
#         """
#         Constructor.
# 
#         :param layout: Blender gui element as passed to the
#             :meth:`robot_designer_plugin.interface.main.UserInterface.draw` method.
#         """
#         self.messages = []
#         self.layout = layout
# 
#     def add_message(self, message):
#         """
#         Adds a string message to the info box.
# 
#         :param message: message
#         :type message: str
#         """
#         self.messages.append(message)
# 
#     def draw_info(self, additional_messages=[], icon=StringConstants.info):
#         """
#         Draws the info box onto the layout.
# 
#         :param additional_messages: Additional messages can be appended.
#         """
#         messages = self.messages + additional_messages
#         if messages:
# 
#             column = self.layout.column(align=True)
#             for text in set(messages):
#                 column.label(text=text, icon=icon)
# 
#     @classmethod
#     def draw_global_info(cls, layout):
# 
#         if cls.global_messages:
#             ib = InfoBox(layout)
#             ib.draw_info(additional_messages=cls.global_messages, icon=StringConstants.error)


# Path: robot_designer_plugin/core/operators.py
import inspect
import bpy
from .config import PLUGIN_PREFIX, EXCEPTION_MESSAGE
from .logfile import log_callstack, log_callstack_last, operator_logger as logger
from .conditions import Condition
from .gui import InfoBox


        bpy.ops.plugin_name.newop(test="Hello World)


    This example show an operator that opens a window containing the message *"Hello World"*. While this is feasible
    for smaller plugins, what happens, if you have a lot of operators written, and you want to have code completion.
    What happens if you want to refactor the names of of the identifier or class attributes. While for the latter there
    is no simple solution available, the :mod:`robot_designer_plugin.core` provides this wrapper class with
    an additional ``run(**kwargs)`` method (that can---and should---be overridden to provide keyword completion).
    Furthermore, it provides decorators for automatically setting preconditions (that define the
    :meth:`bpy.types.Operator.poll` method) for automatic condition checking, logging functionality and post condition
    checking. Together with the :meth:`.pluginmanager.PluginManager.register` method, this makes developing faster (
    code completion,
    code navigation, less verbosity, ...) and safer.

    An examplary :term:`operator` looks like this:

    .. literalinclude:: ../../../resources/templates/operator.py
        :emphasize-lines: 7-11,16-18, 31-33, 60-62
        :lines: 50-111
        :linenos:

    A template is located in ``<RobotDesignerDirectory>/resources/templates/operator.py`` (where you should insert
    the path to the repository) that can be used to quickly write new operators.
    """

    _pre_conditions = {}
    """Dictionary set by the :meth:`PreConditions` decorator. Stores the :class:`.conditions.Condition` that are
    checked for each :class:`RDOperator` -based operator"""


    logger = logger