Exemple #1
0
    def initialize(cls):
        """
        Initializes all module callbacks
        """

        if cls._initialized:
            return

        default_callbacks = {'Tick': callback.PythonTickCallback}

        try:
            shutdown_type = getattr(dcc_callback.Callback(),
                                    'ShutdownCallback')
        except AttributeError:
            shutdown_type = None

        for callback_name in core_dcc.callbacks():

            # Get callback type from tpDcc.DccCallbacks
            n_type = getattr(core_dcc.DccCallbacks, callback_name)[1]['type']
            if n_type == 'simple':
                callback_type = callback.SimpleCallback
            elif n_type == 'filter':
                callback_type = callback.FilterCallback
            else:
                logger.warning(
                    'Callback Type "{}" is not valid! Using Simplecallback instead ...'
                    .format(n_type))
                callback_type = callback.SimpleCallback

            # We extract callback types from the specific registered callbacks module
            if not dcc_callback.Callback():
                logger.warning('DCC {} has no callbacks registered!'.format(
                    dcc.get_name()))
                return

            callback_class = getattr(dcc_callback.Callback(),
                                     '{}Callback'.format(callback_name), None)
            if not callback_class:
                callback_class = default_callbacks.get(callback_name,
                                                       callback.ICallback)
                logger.debug(
                    'Dcc {} does not provides an ICallback for {}Callback. Using {} instead'
                    .format(dcc.get_name(), callback_name,
                            callback_class.__name__))

            new_callback = CallbacksManager._callbacks.get(callback_name, None)
            if new_callback:
                new_callback.cleanup()

            CallbacksManager._callbacks[callback_name] = callback_type(
                callback_class, shutdown_type)

            logger.debug('Creating Callback "{}" of type "{}" ...'.format(
                callback_name, callback_class))

        cls._initialized = True
Exemple #2
0
def create_plugin_instance(plugin_class, already_registered_plugins=None, **kwargs):
    """
    Creates a tool instance of the given class
    :param plugin_class: cls
    :param already_registered_plugins: list
    :return:
    """

    if already_registered_plugins is None:
        already_registered_plugins = list()

    if not plugin_class:
        return

    is_singleton = plugin_class.IS_SINGLETON
    if is_singleton:
        if plugin_class.NAME in [t.NAME for t in already_registered_plugins]:
            for registered_plugin in already_registered_plugins:
                if registered_plugin.NAME == plugin_class.NAME:
                    registered_plugin.show()
                    registered_plugin.show_plugin()
                    return registered_plugin
            return None

    supported_softwares = plugin_class.SUPPORTED_SOFTWARES
    if 'any' not in supported_softwares:
        if dcc.get_name() not in supported_softwares:
            logger.warning(
                'Plugin {} is not suppported in current software: "{}"'.format(plugin_class.NAME, dcc.get_name()))
            return None

    # if python.is_python2():
    #     plugin_kwargs = inspect.getargspec(plugin_class.__init__)
    #     # plugin_kwargs = plugin_kwargs.keywords
    #     plugin_kwargs = plugin_kwargs.args
    # else:
    #     plugin_kwargs = inspect.signature(plugin_class.__init__)
    #     plugin_kwargs = plugin_kwargs.kwargs
    plugin_kwargs = inspect.getargspec(plugin_class.__init__)
    # plugin_kwargs = plugin_kwargs.keywords
    plugin_kwargs = plugin_kwargs.args
    if not plugin_kwargs:
        return plugin_class()

    valid_kwargs = dict()
    for kwarg_name, kwarg_value in kwargs.items():
        if kwarg_name in plugin_kwargs:
            valid_kwargs[kwarg_name] = kwarg_value
    if not valid_kwargs:
        return plugin_class()

    return plugin_class(**valid_kwargs)
Exemple #3
0
    def get_config_paths(self, module_config_name, skip_non_existent=True):
        """
        Returns a list of valid paths where configuration files can be located
        :return: list(str)
        """

        found_paths = list()
        for config_path in self._config_paths:
            root_path = os.path.join(config_path, module_config_name)
            dcc_config_path = os.path.join(config_path, dcc.get_name(),
                                           module_config_name)
            dcc_version_config_path = os.path.join(config_path, dcc.get_name(),
                                                   dcc.get_version_name(),
                                                   module_config_name)
            for p in [root_path, dcc_config_path, dcc_version_config_path]:
                if skip_non_existent:
                    if p and os.path.isfile(p) and p not in found_paths:
                        found_paths.append(p)
                else:
                    if p and p not in found_paths:
                        found_paths.append(p)

        return found_paths
Exemple #4
0
    def _init(self):
        """
        Internal function that initializes info for the plugin and its environment
        """

        self._info.update({
            'name': self._command.__class__.__name__,
            'creator': self._command.creator,
            'module': self._command.__class__.__module__,
            'filepath': inspect.getfile(self._command.__class__),
            'id': self._command.id,
            'application': dcc.get_name()
        })
        self._info.update(osplatform.machine_info())
Exemple #5
0
 def show_color_editor(self):
     if dcc.is_maya():
         import maya.cmds as cmds
         cmds.colorEditor(rgbValue=(self._color.redF(),
                                    self._color.greenF(),
                                    self._color.blueF()))
         if not cmds.colorEditor(query=True, result=True):
             return
         new_color = cmds.colorEditor(query=True, rgbValue=True)
         self.color = QColor.fromRgbF(new_color[0], new_color[1],
                                      new_color[2])
         self.colorChanged.emit()
     else:
         raise RuntimeError(
             'Code Editor is not available for DCC: {}'.format(
                 dcc.get_name()))
Exemple #6
0
    def create_and_connect_to_server(cls, tool_id, *args, **kwargs):

        # def _connect_client():
        #     valid_connect = client.connect()
        #     if not valid_connect:
        #         cls._register_client(tool_id, client)
        #         return False

        client = cls.create(tool_id, *args, **kwargs)

        parent = kwargs.get('parent', None)
        server_class_name = kwargs.get(
            'server_name',
            cls.__name__.replace('Client',
                                 'Server').replace('client', 'server'))
        server_module_name = kwargs.get('server_module_name', 'server')

        if not dcc.is_standalone():
            dcc_mod_name = '{}.dccs.{}.{}'.format(tool_id.replace('-', '.'),
                                                  dcc.get_name(),
                                                  server_module_name)
            try:
                mod = importlib.import_module(dcc_mod_name)
                if hasattr(mod, server_class_name):
                    server = getattr(mod,
                                     server_class_name)(parent,
                                                        client=client,
                                                        update_paths=False)
                    client.set_server(server)
                    client.update_client(tool_id=tool_id, **kwargs)
            except Exception as exc:
                LOGGER.warning(
                    'Impossible to launch tool server! Error while importing: {} >> {}'
                    .format(dcc_mod_name, exc))
                try:
                    server.close_connection()
                except Exception:
                    pass
                return None
        else:
            client.connect()
            client.update_client(tool_id=tool_id, **kwargs)

        return client
Exemple #7
0
def register_package_path(package_name, module_name, config_path, environment='development', config_extension=None):
    """
    Registers configurations path for given package
    :param package_name: str, name of the package configuration files belong to
    :param module_name: str, name of the module this configuration belongs to
    :param config_path: str, path where configuration file is located
    :param environment: str, environment package is working on ('development' or 'production')
    :param config_extension: str, extension used by the configuration file
    """

    config_extension = config_extension or 'yml'
    if not config_extension.startswith('.'):
        config_extension = '.{}'.format(config_extension)

    if not config_path or not os.path.isdir(config_path):
        LOGGER.warning('Configuration Path "{}" for package "{}" does not exists!'.format(config_path, package_name))
        return

    if environment:
        config_path = os.path.join(config_path, environment.lower())
        if not os.path.isdir(config_path):
            LOGGER.warning(
                'Configuration Folder for environment "{}" and package "{}" does not exists "{}"'.format(
                    environment, package_name, config_path))
            return

    dcc_name = dcc.get_name()
    dcc_version = dcc.get_version_name()

    base_config = os.path.join(config_path, module_name)
    dcc_config_path = os.path.join(config_path, dcc_name, module_name)
    dcc_version_config_path = os.path.join(config_path, dcc_name, dcc_version, module_name)

    if package_name not in _PACKAGE_CONFIGS:
        _PACKAGE_CONFIGS[package_name] = dict()
    if module_name not in _PACKAGE_CONFIGS[package_name]:
        _PACKAGE_CONFIGS[package_name][module_name] = dict()

    _PACKAGE_CONFIGS[package_name][module_name][environment] = {
        'base': '{}{}'.format(base_config, config_extension),
        'dcc': '{}{}'.format(dcc_config_path, config_extension),
        'dcc_version': '{}{}'.format(dcc_version_config_path, config_extension)
    }
Exemple #8
0
    def setup_client(self):

        self._client = renamerclient.RenamerClient()
        self._client.signals.dccDisconnected.connect(self._on_dcc_disconnected)

        if not dcc.is_standalone():
            dcc_mod_name = '{}.dccs.{}.renamerserver'.format(
                TOOL_ID.replace('-', '.'), dcc.get_name())
            try:
                mod = importlib.import_module(dcc_mod_name)
                if hasattr(mod, 'RenamerServer'):
                    server = mod.RenamerServer(self,
                                               client=self._client,
                                               update_paths=False)
                    self._client.set_server(server)
                    self._update_client()
            except Exception as exc:
                LOGGER.warning(
                    'Impossible to launch Renamer server! Error while importing: {} >> {}'
                    .format(dcc_mod_name, exc))
                return
        else:
            self._update_client()
Exemple #9
0
    def stylesheet_file(self):
        """
        Returns path where theme stylesheet is located
        :return: str
        """

        style_name = self._style or 'default'
        dcc_name = dcc.get_name()
        dcc_version = dcc.get_version()
        dcc_style = '{}_{}{}'.format(style_name, dcc_name, dcc_version)
        all_styles = [dcc_style, style_name]

        style_extension = style.StyleSheet.EXTENSION
        if not style_extension.startswith('.'):
            style_extension = '.{}'.format(style_extension)

        for style_name in all_styles:
            style_file_name = '{}{}'.format(style_name, style_extension)
            style_path = resources.get('styles', style_file_name)
            if style_path and os.path.isfile(style_path):
                return style_path

        return style_path
Exemple #10
0
    def load_category(self, shelf_file, category_name, clear=True):
        """
        Loads into a shelf all the items of given category name, if exists
        :param category_name: str, name of the category
        """

        if clear:
            self.clear_list()

        with open(shelf_file) as f:
            shelf_data = json.load(f, object_pairs_hook=OrderedDict)

            for item, item_data in shelf_data.items():
                if item != category_name:
                    continue

                all_tools = list()
                for i in item_data:
                    annotation = i.get('annotation')
                    if annotation == 'separator':
                        continue
                    dcc = i.get('dcc')
                    if dcc.get_name() not in dcc:
                        continue
                    icon = os.path.join(self.ICONS_PATHS, i.get('icon'))
                    command = i.get('command')
                    label = i.get('label')
                    new_tool = self.add_button(label=label,
                                               command=command,
                                               icon=icon,
                                               tooltip=annotation)
                    if new_tool:
                        all_tools.append(new_tool)
                current_shelf = gui.get_shelf(
                    shelf_name='{}_{}'.format(self.name, item))
                if current_shelf and all_tools:
                    current_shelf.setTools(all_tools)
Exemple #11
0
    def load_plugin(self,
                    pkg_name,
                    pkg_loaders,
                    environment,
                    root_pkg_name=None,
                    config_dict=None,
                    load=True):
        """
        Implements load_plugin function
        Registers a plugin instance to the manager
        :param pkg_name: str
        :param pkg_loaders: plugin instance to register
        :param environment:
        :param root_pkg_name:
        :param config_dict:
        :param load:
        :return: Plugin
        """

        from tpDcc.managers import configs

        if not pkg_loaders:
            return False

        package_loader = pkg_loaders[0] if isinstance(pkg_loaders,
                                                      (list,
                                                       tuple)) else pkg_loaders
        if not package_loader:
            return False

        if hasattr(package_loader, 'loader'):
            if not package_loader.loader:
                return False

        plugin_path = package_loader.filename if python.is_python2(
        ) else os.path.dirname(package_loader.loader.path)
        plugin_name = package_loader.fullname if python.is_python2(
        ) else package_loader.loader.name

        if not config_dict:
            config_dict = dict()

        config_dict.update({
            'join': os.path.join,
            'user': os.path.expanduser('~'),
            'filename': plugin_path,
            'fullname': plugin_name,
            'root': path_utils.clean_path(plugin_path)
        })

        if pkg_name not in self._plugins:
            self._plugins[pkg_name] = dict()

        libs_found = list()
        version_found = None
        init_fn = None
        mods_found = list()
        # packages_to_walk = [plugin_path] if python.is_python2() else [os.path.dirname(plugin_path)]
        for module_path in modules.iterate_modules(plugin_path,
                                                   skip_inits=False,
                                                   recursive=False):
            module_dot_path = modules.convert_to_dotted_path(module_path)
            try:
                mod = modules.import_module(module_dot_path)
                if not mod:
                    continue
            except Exception:
                continue
            if module_dot_path.endswith('__version__') and hasattr(
                    mod, 'get_version') and callable(mod.get_version):
                if version_found:
                    LOGGER.warning(
                        'Already found version: "{}" for "{}"'.format(
                            version_found, plugin_name))
                else:
                    version_found = getattr(mod, 'get_version')()

            if not init_fn and module_dot_path.endswith('loader') and hasattr(
                    mod, 'init') and callable(mod.init):
                init_fn = mod.init

            mod.LOADED = load
            mods_found.append(mod)

        for mod in mods_found:
            for cname, obj in inspect.getmembers(mod, inspect.isclass):
                for interface in self._interfaces:
                    if issubclass(obj, interface):
                        lib_config_dict = obj.config_dict(
                            file_name=plugin_path) or dict()
                        if not lib_config_dict:
                            continue
                        lib_id = lib_config_dict.get('id', None)
                        tool_config_name = lib_config_dict.get('name', None)
                        if not lib_id:
                            LOGGER.warning(
                                'Impossible to register library "{}" because its ID is not defined!'
                                .format(lib_id))
                            continue
                        if not tool_config_name:
                            LOGGER.warning(
                                'Impossible to register library "{}" because its name is not defined!'
                                .format(tool_config_name))
                            continue
                        if root_pkg_name and root_pkg_name in self._plugins and lib_id in self._plugins[
                                root_pkg_name]:
                            LOGGER.warning(
                                'Impossible to register library "{}" because its ID "{}" its already defined!'
                                .format(tool_config_name, lib_id))
                            continue

                        if not version_found:
                            version_found = '0.0.0'
                        obj.VERSION = version_found
                        obj.FILE_NAME = plugin_path
                        obj.FULL_NAME = plugin_name

                        libs_found.append((module_path, version_found, obj))
                        version_found = True
                        break

        if not libs_found:
            LOGGER.warning(
                'No libraries found in module "{}". Skipping ...'.format(
                    plugin_path))
            return False
        if len(libs_found) > 1:
            LOGGER.warning(
                'Multiple libraries found ({}) in module "{}". Loading first one. {} ...'
                .format(len(libs_found), plugin_path, libs_found[-1]))
            lib_found = libs_found[-1]
        else:
            lib_found = libs_found[0]
        lib_loader = modules.convert_to_dotted_path(lib_found[0])
        lib_loader = loader.find_loader(lib_loader)

        # Check if DCC specific implementation for plugin exists
        dcc_path = '{}.dccs.{}'.format(plugin_name, dcc.get_name())
        dcc_loader = None
        dcc_config = None
        try:
            dcc_loader = loader.find_loader(dcc_path)
        except ImportError:
            pass

        lib_config_dict = lib_found[2].config_dict(
            file_name=plugin_path) or dict()
        lib_id = lib_config_dict['id']
        _tool_name = lib_config_dict['name']

        tool_config_name = plugin_name.replace('.', '-')
        lib_config = configs.get_config(config_name=tool_config_name,
                                        package_name=pkg_name,
                                        root_package_name=root_pkg_name,
                                        environment=environment,
                                        config_dict=config_dict,
                                        extra_data=lib_config_dict)

        if dcc_loader:
            dcc_path = dcc_loader.fullname
            dcc_config = configs.get_config(config_name=dcc_path.replace(
                '.', '-'),
                                            package_name=pkg_name,
                                            environment=environment,
                                            config_dict=config_dict)
            if not dcc_config.get_path():
                dcc_config = None

        # Register resources
        def_resources_path = os.path.join(plugin_path, 'resources')
        # resources_path = plugin_config.data.get('resources_path', def_resources_path)
        resources_path = lib_config_dict.get('resources_path', None)
        if not resources_path or not os.path.isdir(resources_path):
            resources_path = def_resources_path
        if os.path.isdir(resources_path):
            resources.register_resource(resources_path, key='tools')
        else:
            pass
            # tp.logger.debug('No resources directory found for plugin "{}" ...'.format(_plugin_name))

        # Register DCC specific resources
        if dcc_loader and dcc_config:
            def_resources_path = os.path.join(dcc_loader.filename, 'resources')
            resources_path = dcc_config.data.get('resources_path',
                                                 def_resources_path)
            if not resources_path or not os.path.isdir(resources_path):
                resources_path = def_resources_path
            if os.path.isdir(resources_path):
                resources.register_resource(resources_path, key='plugins')
            else:
                pass
                # tp.logger.debug('No resources directory found for plugin "{}" ...'.format(_plugin_name))

        # Create lib loggers directory
        default_logger_dir = os.path.normpath(
            os.path.join(os.path.expanduser('~'), 'tpDcc', 'logs', 'libs'))
        default_logging_config = os.path.join(plugin_path, '__logging__.ini')
        logger_dir = lib_config_dict.get('logger_dir', default_logger_dir)
        if not os.path.isdir(logger_dir):
            os.makedirs(logger_dir)
        logging_file = lib_config_dict.get('logging_file',
                                           default_logging_config)

        lib_package = plugin_name
        lib_package_path = plugin_path
        dcc_package = None
        dcc_package_path = None
        if dcc_loader:
            dcc_package = dcc_loader.fullname if python.is_python2(
            ) else dcc_loader.loader.path
            dcc_package_path = dcc_loader.filename if python.is_python2(
            ) else dcc_loader.loader.name

        self._plugins[pkg_name][lib_id] = {
            'name': _tool_name,
            'package_name': pkg_name,
            'loader': package_loader,
            'config': lib_config,
            'config_dict': lib_config_dict,
            'plugin_loader': lib_loader,
            'plugin_package': lib_package,
            'plugin_package_path': lib_package_path,
            'version': lib_found[1] if lib_found[1] is not None else "0.0.0",
            'dcc_loader': dcc_loader,
            'dcc_package': dcc_package,
            'dcc_package_path': dcc_package_path,
            'dcc_config': dcc_config,
            'logging_file': logging_file,
            'plugin_instance': None
        }

        if init_fn:
            try:
                dev = True if environment == 'development' else False
                init_fn(dev=dev)
                LOGGER.info(
                    'Library "{}" registered and initialized successfully!'.
                    format(plugin_name))
            except Exception:
                LOGGER.warning(
                    'Library "{}" registered successfully but its initialization failed: {}'
                    .format(plugin_name, traceback.format_exc()))
        else:
            LOGGER.info(
                'Library "{}" registered successfully!'.format(plugin_name))

        return True
Exemple #12
0
    def load_plugin(self,
                    pkg_name,
                    pkg_loaders,
                    environment,
                    root_pkg_name=None,
                    config_dict=None,
                    load=True):
        """
        Implements load_plugin function
        Registers a plugin instance to the manager
        :param pkg_name: str
        :param pkg_loaders: plugin instance to register
        :param environment:
        :param root_pkg_name:
        :param config_dict:
        :param load:
        :return: Plugin
        """

        if not pkg_loaders:
            return False

        package_loader = pkg_loaders[0] if isinstance(pkg_loaders,
                                                      (list,
                                                       tuple)) else pkg_loaders
        if not package_loader:
            return False

        if hasattr(package_loader, 'loader'):
            if not package_loader.loader:
                return False

        plugin_path = package_loader.filename if python.is_python2(
        ) else os.path.dirname(package_loader.loader.path)
        plugin_name = package_loader.fullname if python.is_python2(
        ) else package_loader.loader.name

        if not config_dict:
            config_dict = dict()

        local = os.getenv('APPDATA') or os.getenv('HOME')

        config_dict.update({
            'join': os.path.join,
            'user': os.path.expanduser('~'),
            'filename': plugin_path,
            'fullname': plugin_name,
            'root': path_utils.clean_path(plugin_path),
            'local': local,
            'home': local
        })

        if pkg_name not in self._plugins:
            self._plugins[pkg_name] = dict()

        tools_found = list()
        version_found = None
        packages_to_walk = [plugin_path] if python.is_python2() else [
            os.path.dirname(plugin_path)
        ]
        for sub_module in pkgutil.walk_packages(packages_to_walk):
            importer, sub_module_name, _ = sub_module
            qname = '{}.{}'.format(plugin_name, sub_module_name)
            try:
                mod = importer.find_module(sub_module_name).load_module(
                    sub_module_name)
            except Exception:
                # LOGGER.exception('Impossible to register plugin: "{}"'.format(plugin_path))
                continue

            if qname.endswith('__version__') and hasattr(mod, '__version__'):
                if version_found:
                    LOGGER.warning(
                        'Already found version: "{}" for "{}"'.format(
                            version_found, plugin_name))
                else:
                    version_found = getattr(mod, '__version__')

            mod.LOADED = load

            for cname, obj in inspect.getmembers(mod, inspect.isclass):
                for interface in self._interfaces:
                    if issubclass(obj, interface):
                        tool_config_dict = obj.config_dict(
                            file_name=plugin_path) or dict()
                        if not tool_config_dict:
                            continue
                        tool_id = tool_config_dict.get('id', None)
                        tool_config_name = tool_config_dict.get('name', None)
                        # tool_icon = tool_config_dict.get('icon', None)
                        if not tool_id:
                            LOGGER.warning(
                                'Impossible to register tool "{}" because its ID is not defined!'
                                .format(tool_id))
                            continue
                        if not tool_config_name:
                            LOGGER.warning(
                                'Impossible to register tool "{}" because its name is not defined!'
                                .format(tool_config_name))
                            continue
                        if root_pkg_name and root_pkg_name in self._plugins and tool_id in self._plugins[
                                root_pkg_name]:
                            LOGGER.warning(
                                'Impossible to register tool "{}" because its ID "{}" its already defined!'
                                .format(tool_config_name, tool_id))
                            continue

                        if not version_found:
                            version_found = '0.0.0'
                        obj.VERSION = version_found
                        obj.FILE_NAME = plugin_path
                        obj.FULL_NAME = plugin_name

                        tools_found.append((qname, version_found, obj))
                        version_found = True
                        break

        if not tools_found:
            LOGGER.warning(
                'No tools found in module "{}". Skipping ...'.format(
                    plugin_path))
            return False
        if len(tools_found) > 1:
            LOGGER.warning(
                'Multiple tools found ({}) in module "{}". Loading first one. {} ...'
                .format(len(tools_found), plugin_path, tools_found[-1]))
            tool_found = tools_found[-1]
        else:
            tool_found = tools_found[0]
        tool_loader = loader.find_loader(tool_found[0])

        # Check if DCC specific implementation for plugin exists
        dcc_path = '{}.dccs.{}'.format(plugin_name, dcc.get_name())
        dcc_loader = None
        dcc_config = None
        try:
            dcc_loader = loader.find_loader(dcc_path)
        except ImportError:
            pass

        tool_config_dict = tool_found[2].config_dict(
            file_name=plugin_path) or dict()
        tool_id = tool_config_dict['id']
        _tool_name = tool_config_dict['name']
        tool_icon = tool_config_dict['icon']

        tool_config_name = plugin_name.replace('.', '-')
        tool_config = configs.get_config(config_name=tool_config_name,
                                         package_name=pkg_name,
                                         root_package_name=root_pkg_name,
                                         environment=environment,
                                         config_dict=config_dict,
                                         extra_data=tool_config_dict)

        if dcc_loader:
            dcc_path = dcc_loader.fullname
            dcc_config = configs.get_config(config_name=dcc_path.replace(
                '.', '-'),
                                            package_name=pkg_name,
                                            environment=environment,
                                            config_dict=config_dict)
            if not dcc_config.get_path():
                dcc_config = None

        # Register resources
        def_resources_path = os.path.join(plugin_path, 'resources')
        # resources_path = plugin_config.data.get('resources_path', def_resources_path)
        resources_path = tool_config_dict.get('resources_path', None)
        if not resources_path or not os.path.isdir(resources_path):
            resources_path = def_resources_path
        if os.path.isdir(resources_path):
            resources.register_resource(resources_path, key='tools')
        else:
            pass
            # tp.logger.debug('No resources directory found for plugin "{}" ...'.format(_plugin_name))

        # Register DCC specific resources
        if dcc_loader and dcc_config:
            def_resources_path = os.path.join(dcc_loader.filename, 'resources')
            resources_path = dcc_config.data.get('resources_path',
                                                 def_resources_path)
            if not resources_path or not os.path.isdir(resources_path):
                resources_path = def_resources_path
            if os.path.isdir(resources_path):
                resources.register_resource(resources_path, key='plugins')
            else:
                pass
                # tp.logger.debug('No resources directory found for plugin "{}" ...'.format(_plugin_name))

        # Create tool loggers directory
        default_logger_dir = os.path.normpath(
            os.path.join(os.path.expanduser('~'), 'tpDcc', 'logs', 'tools'))
        default_logging_config = os.path.join(plugin_path, '__logging__.ini')
        logger_dir = tool_config_dict.get('logger_dir', default_logger_dir)
        if not os.path.isdir(logger_dir):
            os.makedirs(logger_dir)
        logging_file = tool_config_dict.get('logging_file',
                                            default_logging_config)

        tool_package = plugin_name
        tool_package_path = plugin_path
        dcc_package = None
        dcc_package_path = None
        if dcc_loader:
            dcc_package = dcc_loader.fullname if python.is_python2(
            ) else dcc_loader.loader.path
            dcc_package_path = dcc_loader.filename if python.is_python2(
            ) else dcc_loader.loader.name

        self._plugins[pkg_name][tool_id] = {
            'name': _tool_name,
            'icon': tool_icon,
            'package_name': pkg_name,
            'loader': package_loader,
            'config': tool_config,
            'config_dict': tool_config_dict,
            'plugin_loader': tool_loader,
            'plugin_package': tool_package,
            'plugin_package_path': tool_package_path,
            'version': tool_found[1] if tool_found[1] is not None else "0.0.0",
            'dcc_loader': dcc_loader,
            'dcc_package': dcc_package,
            'dcc_package_path': dcc_package_path,
            'dcc_config': dcc_config,
            'logging_file': logging_file,
            'plugin_instance': None
        }

        LOGGER.info('Tool "{}" registered successfully!'.format(plugin_name))

        return True