diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 018a8f4208db02b987a0b01dd46ab9e38a7fed93..68c96ed095c77adf40f85426a620dd7396121b60 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,7 +1,7 @@ # this is a gitlab-pipeline for this project # it analysis the shell scripts as well as the python-code --- -image: python:3.8 +image: python:3.10 variables: PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" @@ -47,6 +47,7 @@ pyright: code-quality: stage: static analysis + allow_failure: true needs: - job: pyright artifacts: true diff --git a/pyproject.toml b/pyproject.toml index e82b23733f8aab0e1cb6b50852091255a755cb88..539b136ba882455328899eba583a5f1599580ed5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "scientific_plots" -requires-python = ">=3.8" +requires-python = ">=3.10" description = "Useful methods for plots used in science" readme = "readme.md" authors = [{name = "Felix Fischer", email = "f.fischer@ifas.rwth-aachen.de"}] @@ -66,6 +66,7 @@ warn_unused_ignores = false [tool.pylint.MASTER] fail-under = 9.0 +ignore-patterns = [".*.pyi", ".*-stubs"] [tool.pylint.BASIC] good-names = ["i", "j", "k", "ex", "Run", "_", "ax", "e", "f", "n", "N", diff --git a/src/scientific_plots/__init__.py b/src/scientific_plots/__init__.py index cd5c3dc43d9b96e9fdad53e18564568eece0e349..c500bae615e91eb8956e1c680137841be6a22bea 100644 --- a/src/scientific_plots/__init__.py +++ b/src/scientific_plots/__init__.py @@ -5,4 +5,4 @@ useful across several different projects and repositories. It also contains stub-files with several data-type annotations for scipy and matplot-lib functions.""" -__version__ = "1.8.5" +__version__ = "1.8.6" diff --git a/src/scientific_plots/default_plots.py b/src/scientific_plots/default_plots.py index 00b76b178666a5baa8b4955547ba8d87f030262b..97fbc82a5581f85141c9a3692d719ca960a7543f 100644 --- a/src/scientific_plots/default_plots.py +++ b/src/scientific_plots/default_plots.py @@ -138,6 +138,7 @@ def get_ylims( return ylim +# pylint: disable=too-many-positional-arguments def set_lims( X: In, Y: In, logscale: bool = False, @@ -168,6 +169,7 @@ def set_lims( plt.ylim(*ylim) +# pylint: disable=too-many-positional-arguments @apply_styles def plot_fit(X: In, Y: In, fit_function: Callable[..., float], @@ -198,7 +200,7 @@ def plot_fit(X: In, Y: In, min(X) + (max(X) - min(X)) * i / (n_fit - 1) for i in range(n_fit)] Y_fit = [_fit_function(x) for x in X_fit] - plt.plot(X_fit, Y_fit, label="fit") + plt.plot(X_fit, Y_fit, label="fit") # type: ignore set_lims( X, Y, logscale=logscale, single_log=single_log, @@ -223,6 +225,7 @@ def plot_fit(X: In, Y: In, plt.close() +# pylint: disable=too-many-positional-arguments @apply_styles(three_d=True) def plot_surface(X: In2D, Y: In2D, Z: In2D, xlabel: str, ylabel: str, zlabel: str, diff --git a/src/scientific_plots/plot_settings.py b/src/scientific_plots/plot_settings.py index 5d20654f2c1638d9b2ebcddf4dfcdc1065c12168..9c59947e644b87bc0da515afda254b7b623671e8 100644 --- a/src/scientific_plots/plot_settings.py +++ b/src/scientific_plots/plot_settings.py @@ -7,29 +7,34 @@ the hard drive """ from __future__ import annotations -import csv -import locale from contextlib import contextmanager from copy import copy, deepcopy +import csv from functools import wraps -from typing import ( - Generator, Optional, Union, Callable, Any, overload) +import locale from pathlib import Path -from warnings import warn, catch_warnings, simplefilter +import sys from textwrap import dedent +from typing import Callable, Generator, Optional, Union, overload +from warnings import catch_warnings, simplefilter, warn -# pylint: disable=unused-import -import scienceplots # noqa: F401 -import mpl_toolkits +import numpy as np + +from cycler import cycler import matplotlib as mpl +from matplotlib import colors import matplotlib.pyplot as plt from matplotlib.pyplot import Axes -from matplotlib import colors -from cycler import cycler -import numpy as np +import mpl_toolkits +import scienceplots # noqa: F401 # pylint: disable=unused-import -from .utilities import translate from .types_ import Vector +from .utilities import translate + +if sys.version_info >= (3, 10): + from typing import ParamSpec +else: + from typing_extensions import ParamSpec mpl.use("Agg") plt.rcParams["axes.unicode_minus"] = False @@ -482,33 +487,51 @@ def check_3d(three_d: bool) -> None: raise ThreeDPlotException -PlotFunction = Callable[..., None] +Params = ParamSpec("Params") + + +def supress_warnings(plot_function: Callable[Params, None])\ + -> Callable[Params, None]: + """Print only the first appearance of any type of warning shown + in the function.""" + + @wraps(plot_function) + def wrapped_function( + *args: Params.args, **kwargs: Params.kwargs) -> None: + """Wrapped function without all of the warnings.""" + with catch_warnings(): + simplefilter("once") + plot_function(*args, **kwargs) + + return wrapped_function @overload -def apply_styles(plot_function: PlotFunction, *, +def apply_styles(plot_function: Callable[Params, None], *, three_d: bool = False, - _fallback: bool = False) -> PlotFunction: + _fallback: bool = False) -> Callable[Params, None]: ... @overload def apply_styles(plot_function: None, *, three_d: bool = False, _fallback: bool = False)\ - -> Callable[[PlotFunction], PlotFunction]: + -> Callable[[Callable[Params, None]], Callable[Params, None]]: ... @overload def apply_styles(*, three_d: bool = False, _fallback: bool = False)\ - -> Callable[[PlotFunction], PlotFunction]: + -> Callable[[Callable[Params, None]], Callable[Params, None]]: ... -def apply_styles(plot_function: Optional[PlotFunction] = None, *, +def apply_styles(plot_function: Optional[Callable[Params, None]] = None, *, three_d: bool = False, _fallback: bool = False)\ - -> Union[Callable[[PlotFunction], PlotFunction], PlotFunction]: + -> Union[Callable[[Callable[Params, None]], + Callable[Params, None]], + Callable[Params, None]]: """ Apply the newly defined styles to a function, which creates a plot. The new plots are saved into different subdirectories and multiple @@ -521,12 +544,15 @@ def apply_styles(plot_function: Optional[PlotFunction] = None, *, """ # pylint: disable=too-many-statements - def _decorator(_plot_function: PlotFunction) -> PlotFunction: + def _decorator(_plot_function: Callable[Params, None])\ + -> Callable[Params, None]: """This is the actual decorator. Thus, the outer function 'apply_styles' is actually a decorator-factory.""" @wraps(_plot_function) - def new_plot_function(*args: Any, **kwargs: Any) -> None: + @supress_warnings + def new_plot_function(*args: Params.args, + **kwargs: Params.kwargs) -> None: """ New plotting function, with applied styles. """ @@ -655,6 +681,13 @@ def apply_styles(plot_function: Optional[PlotFunction] = None, *, with plt.style.context("fast"): presentation() + except (ValueError, RuntimeError): + warn(dedent( + f"""Some plots with alternative styles + could not be + created for {_plot_function.__name__}."""), + ImportWarning) + plt.savefig = old_save return new_plot_function @@ -662,4 +695,5 @@ def apply_styles(plot_function: Optional[PlotFunction] = None, *, if plot_function is not None: return _decorator(plot_function) + assert plot_function is None return _decorator diff --git a/src/scientific_plots/utilities.py b/src/scientific_plots/utilities.py index d4ac4619ac851bb3b3c87c71cb2ba10f337e24e6..2475c1a840e6e8d1b3c377b85f6558ae248989d0 100644 --- a/src/scientific_plots/utilities.py +++ b/src/scientific_plots/utilities.py @@ -120,7 +120,6 @@ def dumb_plot(X: List[float], Y: List[float], gnuplot.stdin.flush() except FileNotFoundError: print("There is no installed instance of gnuplot") - return def read_file(filename: Union[str, Path], diff --git a/src/scipy-stubs/optimize.pyi b/src/scipy-stubs/optimize.pyi index 3589a34b69a1e4ce8b1a102a1a067b06edecbf0e..4333a809a6580060caa376d6cc5fae4495bbc731 100644 --- a/src/scipy-stubs/optimize.pyi +++ b/src/scipy-stubs/optimize.pyi @@ -16,7 +16,14 @@ def curve_fit( xdata: Union[Vector, list[float]], ydata: Union[Vector, list[float]], p0: Optional[Union[List[float], tuple[float]]] = None, - bounds: Optional[Any] = None)\ + check_finite: Optional[bool] = None, + bounds: Optional[Any] = None, + jac: Union[Callable[..., Any], str, None] = None, + full_output: bool = False, + ftol: Optional[float] = None, + xtol: Optional[float] = None, + gtol: Optional[float] = None, + method: str = "trf")\ -> Tuple[Vector, Matrix]: ...