def find_external_plugins(): """ Find available external plugins based on setuptools entry points. """ internal_names = get_class_values(Plugins) plugins = list(pkg_resources.iter_entry_points("spyder.plugins")) external_plugins = {} for entry_point in plugins: name = entry_point.name if name not in internal_names: try: class_name = entry_point.attrs[0] mod = importlib.import_module(entry_point.module_name) plugin_class = getattr(mod, class_name, None) # To display in dependencies dialog. plugin_class._spyder_module_name = entry_point.module_name plugin_class._spyder_package_name = ( entry_point.dist.project_name) plugin_class._spyder_version = entry_point.dist.version external_plugins[name] = plugin_class if name != plugin_class.NAME: raise SpyderAPIError( "Entry point name '{0}' and plugin.NAME '{1}' " "do not match!".format(name, plugin_class.NAME)) except (ModuleNotFoundError, ImportError) as error: print("%s: %s" % (name, str(error)), file=STDERR) traceback.print_exc(file=STDERR) return external_plugins
def test_find_internal_plugins(): internal = find_internal_plugins() assert len(internal) == 27 # Assert we have the same number of plugins declared in our enum # 27 internal plugins + the 'All' extra entry assert len(get_class_values(Plugins)) == 27 + 1
def create_toolbars_menu(self): """ Populate the toolbars menu inside the view application menu. """ main_section = ToolbarsMenuSections.Main secondary_section = ToolbarsMenuSections.Secondary default_toolbars = get_class_values(ApplicationToolbars) for toolbar_id, toolbar in self._ADDED_TOOLBARS.items(): if toolbar: action = toolbar.toggleViewAction() if not PYSIDE2: # Modifying __class__ of a QObject created by C++ [1] seems # to invalidate the corresponding Python object when PySide # is used (changing __class__ of a QObject created in # Python seems to work). # # [1] There are Qt functions such as # QToolBar.toggleViewAction(), QToolBar.addAction(QString) # and QMainWindow.addToolbar(QString), which return a # pointer to an already existing QObject. action.__class__ = QActionID action.action_id = f'toolbar_{toolbar_id}' section = (main_section if toolbar_id in default_toolbars else secondary_section) self.add_item_to_menu( action, menu=self.toolbars_menu, section=section, )
def find_internal_plugins(): """ Find internal plugins based on setuptools entry points. """ internal_plugins = {} entry_points = list(pkg_resources.iter_entry_points("spyder.plugins")) internal_names = get_class_values(Plugins) for entry_point in entry_points: name = entry_point.name if name not in internal_names: continue class_name = entry_point.attrs[0] mod = importlib.import_module(entry_point.module_name) plugin_class = getattr(mod, class_name, None) internal_plugins[name] = plugin_class # FIXME: This shouldn't be necessary but it's just to be sure # plugins are sorted in alphabetical order. We need to remove it # in a later version. internal_plugins = { key: value for key, value in sorted(internal_plugins.items()) } return internal_plugins
def create_toolbars_menu(self): """ Populate the toolbars menu inside the view application menu. """ main_section = ToolbarsMenuSections.Main secondary_section = ToolbarsMenuSections.Secondary default_toolbars = get_class_values(ApplicationToolbars) for toolbar_id, toolbar in self._ADDED_TOOLBARS.items(): if toolbar: action = toolbar.toggleViewAction() section = (main_section if toolbar_id in default_toolbars else secondary_section) self.add_item_to_menu( action, menu=self.toolbars_menu, section=section, )
HorizontalSplitLayout, MatlabLayout, RLayout, SpyderLayout, VerticalSplitLayout) from spyder.plugins.preferences.widgets.container import PreferencesActions from spyder.plugins.toolbar.api import ( ApplicationToolbars, MainToolbarSections) from spyder.py3compat import qbytearray_to_str # FIXME: # Localization _ = get_translation("spyder") # Constants # Number of default layouts available DEFAULT_LAYOUTS = get_class_values(DefaultLayouts) # ---------------------------------------------------------------------------- # ---- Window state version passed to saveState/restoreState. # ---------------------------------------------------------------------------- # This defines the layout version used by different Spyder releases. In case # there's a need to reset the layout when moving from one release to another, # please increase the number below in integer steps, e.g. from 1 to 2, and # leave a mention below explaining what prompted the change. # # The current versions are: # # * Spyder 4: Version 0 (it was the default). # * Spyder 5.0.0 to 5.0.5: Version 1 (a bump was required due to the new API). # * Spyder 5.1.0: Version 2 (a bump was required due to the migration of # Projects to the new API).
def find_internal_plugins(): """ Find internal plugins based on setup.py entry points. In DEV mode we parse the `setup.py` file directly. """ internal_plugins = {} # If DEV, look for entry points in setup.py file for internal plugins # and then look on the system for the rest HERE = os.path.abspath(os.path.dirname(__file__)) base_path = os.path.dirname(os.path.dirname(HERE)) setup_path = os.path.join(base_path, "setup.py") if (DEV or running_under_pytest()) and not running_in_ci(): if not os.path.isfile(setup_path): raise Exception( 'No "setup.py" file found and running in DEV mode!') with open(setup_path, "r") as fh: lines = fh.read().split("\n") start = None end = None for idx, line in enumerate(lines): if line.startswith("spyder_plugins_entry_points"): start = idx + 1 continue if start is not None: if line.startswith("]"): end = idx + 1 break entry_points_list = "[" + "\n".join(lines[start:end]) spyder_plugin_entry_points = ast.literal_eval(entry_points_list) for entry_point in spyder_plugin_entry_points: try: name, module = entry_point.split(" = ") name = name.strip() module = module.strip() module, class_name = module.split(":") except Exception: logger.error( '"setup.py" entry point "{entry_point}" is malformed!' "".format(entry_point=entry_point)) try: mod = importlib.import_module(module) internal_plugins[name] = getattr(mod, class_name, None) except (ModuleNotFoundError, ImportError) as e: raise e else: entry_points = list(pkg_resources.iter_entry_points("spyder.plugins")) internal_names = get_class_values(Plugins) for entry_point in entry_points: name = entry_point.name if name not in internal_names: continue class_name = entry_point.attrs[0] mod = importlib.import_module(entry_point.module_name) plugin_class = getattr(mod, class_name, None) internal_plugins[name] = plugin_class # FIXME: This shouldn't be necessary but it's just to be sure # plugins are sorted in alphabetical order. We need to remove it # in a later version. internal_plugins = { key: value for key, value in sorted(internal_plugins.items()) } return internal_plugins
def test_find_internal_plugins(): internal = find_internal_plugins() assert len(internal) == 26 # Assert we have the same number of plugins declared in our enum assert len(get_class_values(Plugins)) == 26