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
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)
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
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())
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()))
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
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) }
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()
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
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)
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
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