Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #3
0
    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,
                )
Beispiel #4
0
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
Beispiel #5
0
    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,
                )
Beispiel #6
0
                                           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).
Beispiel #7
0
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
Beispiel #8
0
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