Source code for psyplot_gui.config.rcsetup

"""Default management of the psyplot_gui package

This module defines the necessary configuration parts for the psyplot gui"""

# SPDX-FileCopyrightText: 2016-2024 University of Lausanne
# SPDX-FileCopyrightText: 2020-2021 Helmholtz-Zentrum Geesthacht
# SPDX-FileCopyrightText: 2021-2024 Helmholtz-Zentrum hereon GmbH
#
# SPDX-License-Identifier: LGPL-3.0-only

import logging

import six
from matplotlib.rcsetup import validate_bool, validate_int
from psyplot.config.rcsetup import (
    RcParams,
    psyplot_fname,
    validate_bool_maybe_none,
    validate_stringlist,
)


[docs] def try_and_error(*funcs): """Apply multiple validation functions Parameters ---------- ``*funcs`` Validation functions to test Returns ------- function""" def validate(value): exc = None for func in funcs: try: return func(value) except (ValueError, TypeError) as e: exc = e raise exc return validate
# ----------------------------------------------------------------------------- # ------------------------- validation functions ------------------------------ # -----------------------------------------------------------------------------
[docs] def validate_str(s): """Validate a string Parameters ---------- s: str Returns ------- str Raises ------ ValueError""" if not isinstance(s, six.string_types): raise ValueError("Did not found string!") return six.text_type(s)
[docs] def validate_none(b): """Validate that None is given Parameters ---------- b: {None, 'none'} None or string (the case is ignored) Returns ------- None Raises ------ ValueError""" if isinstance(b, six.string_types): b = b.lower() if b is None or b == "none": return None else: raise ValueError('Could not convert "%s" to None' % b)
[docs] def validate_all(v): """Test if ``v == 'all'``""" if v != "all": raise ValueError("The value must be 'all'") return six.text_type(v)
[docs] class GuiRcParams(RcParams): """RcParams for the psyplot-gui package.""" HEADER = RcParams.HEADER.replace( "psyplotrc.yml", "psyplotguirc.yml" ).replace("PSYPLOTRC", "psyplotrc.yml")
[docs] def load_from_file(self, fname=None): """ Update rcParams from user-defined settings This function updates the instance with what is found in `fname` Parameters ---------- fname: str Path to the yaml configuration file. Possible keys of the dictionary are defined by :data:`config.rcsetup.defaultParams`. If None, the :func:`config.rcsetup.psyplot_fname` function is used. See Also -------- dump_to_file, psyplot_fname""" fname = fname or psyplot_fname( env_key="PSYPLOTGUIRC", fname="psyplotguirc.yml" ) if fname: super(GuiRcParams, self).load_from_file(fname)
def _load_plugin_entrypoints(self): """Load the modules for the psyplot plugins Yields ------ pkg_resources.EntryPoint The entry point for the psyplot plugin module""" from pkg_resources import iter_entry_points inc = self["plugins.include"] exc = self["plugins.exclude"] logger = logging.getLogger(__name__) self._plugins = self._plugins or [] for ep in iter_entry_points("psyplot_gui"): try: ep.module except AttributeError: # python<3.10 try: ep.module = ep.pattern.match(ep.value).group("module") except AttributeError: # python<3.8 ep.module = ep.module_name plugin_name = "%s:%s:%s" % (ep.module, ":".join(ep.attrs), ep.name) # check if the user wants to explicitly this plugin include_user = None if inc: include_user = ( ep.module in inc or ep.name in inc or "%s:%s" % (ep.module, ":".join(ep.attrs)) in inc ) if include_user is None and exc == "all": include_user = False elif include_user is None: # check for exclude include_user = not ( ep.module in exc or ep.name in exc or "%s:%s" % (ep.module, ":".join(ep.attrs)) in exc ) if not include_user: logger.debug( "Skipping plugin %s: Excluded by user", plugin_name ) else: logger.debug("Loading plugin %s", plugin_name) self._plugins.append(str(ep)) yield ep
[docs] def load_plugins(self, *args, **kwargs): """ Load the plugins for the psyplot_gui MainWindow Returns ------- dict A mapping from entry point name to the imported widget class Notes ----- ``*args`` and ``**kwargs`` are ignored """ def format_ep(ep): return "%s:%s:%s" % (ep.module_name, ":".join(ep.attrs), ep.name) return { format_ep(ep): ep.load() for ep in self._load_plugin_entrypoints() }
#: :class:`dict` with default values and validation functions defaultParams = { # gui settings "backend": [ "psyplot", try_and_error(validate_str, validate_none), "Backend to use when using the graphical user interface. The current " "backend is used and no changes are made. Note that it is usually not " "possible to change the backend after importing the psyplot.project " "module. The default backend embeds the figures into the ", ], "help_explorer.use_webengineview": [ True, validate_bool, "Enable the PyQt5.QtWebEngineWidgets.QWebEngineView which might not " "work under certain circumstances.", ], "help_explorer.use_intersphinx": [ None, validate_bool_maybe_none, "Use the intersphinx extension and link to the online documentations " "of matplotlib, pyplot, psyplot, numpy, etc. when converting rst " "docstrings. The inventories are loaded when the first object is " "documented. If None, intersphinx is only used when " "`help_explorer.online` is True and you are not using windows", ], "help_explorer.render_docs_parallel": [ True, validate_bool, "Boolean whether the html docs are rendered in a separate process", ], "help_explorer.online": [ None, validate_bool_maybe_none, "Switch that controls whether the online functions of the help " "explorer shall be enabled. False implies that " "help_explorer.use_intersphinx is set to False", ], "console.start_channels": [ True, validate_bool, "Start the different channels of the KernelClient", ], "console.connect_to_help": [ True, validate_bool, "Whether the console shall be connected to the help_explorer or not", ], "console.auto_set_mp": [ True, validate_bool, "If True, then the 'mp' variable in the console is automatically set " "when the current main project changes", ], "console.auto_set_sp": [ True, validate_bool, "If True, then the 'sp' variable in the console is automatically set " "when the current sub project changes", ], "main.open_files_port": [ 30124, validate_int, "The port number used when new files are opened", ], "main.listen_to_port": [ True, validate_bool, "If True and the psyplot gui is already running, new files are opened " "in that gui", ], "main.opengl": [ "software", validate_str, "The opengl implementation to use. Should be one of 'software', " "'desktop', 'gles' or 'automatic'.", ], "content.load_tooltips": [ True, validate_bool, "If True, a lazy load is performed on the arrays and data sets and " "their string representation is displayed as tool tip. This part of " "the data into memory. It is recommended to set this to False for " "remote data.", ], "fmt.sort_by_key": [ True, validate_bool, "If True, the formatoptions in the Formatoptions widget are sorted by " "their formatoption key rather than by their name.", ], "plugins.include": [ None, try_and_error(validate_none, validate_stringlist), "The plugins to load. Can be either None to load all that are not " "explicitly excluded by the 'plugins.exclude' key or a list of " "plugins to include. List items can be either module names, plugin " "names or the module name and widget via '<module_name>:<widget>'", ], "plugins.exclude": [ [], try_and_error(validate_all, validate_stringlist), "The plugins to exclude from loading. Can be either 'all' to exclude " "all plugins or a list like in 'plugins.include'.", ], } #: :class:`~psyplot.config.rcsetup.RcParams` instance that stores default #: formatoptions and configuration settings. rcParams = GuiRcParams(defaultParams=defaultParams) rcParams.update({key: val[0] for key, val in defaultParams.items()}) rcParams.load_from_file()