diff --git a/src/pyoctaveband/__init__.py b/src/pyoctaveband/__init__.py index 422dbdf..0524992 100644 --- a/src/pyoctaveband/__init__.py +++ b/src/pyoctaveband/__init__.py @@ -8,7 +8,6 @@ from typing import List, Tuple, overload, Literal -import matplotlib import numpy as np from .calibration import calculate_sensitivity @@ -17,9 +16,6 @@ from .parametric_filters import WeightingFilter, linkwitz_riley, time_weighting, weighting_filter from ._version import __version__ -# Use non-interactive backend for plots -matplotlib.use("Agg") - # Public methods __all__ = [ "__version__", diff --git a/src/pyoctaveband/_version.py b/src/pyoctaveband/_version.py index bc86c94..10aa336 100644 --- a/src/pyoctaveband/_version.py +++ b/src/pyoctaveband/_version.py @@ -1 +1 @@ -__version__ = "1.2.2" +__version__ = "1.2.3" diff --git a/tests/conftest.py b/tests/conftest.py index 74d3d1a..d737c7c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,6 +2,13 @@ import os import pytest +# Select a non-interactive matplotlib backend for the headless test suite. +# The library no longer forces a backend (see issue #52), so the test harness +# must opt into Agg itself; otherwise matplotlib picks a GUI backend (e.g. +# TkAgg on Windows runners) and figure creation fails without a display/Tcl. +# Set at import time so it takes effect before any test module imports pyplot. +os.environ.setdefault("MPLBACKEND", "Agg") + def pytest_configure(config): """ Configure environment variables for the test session. diff --git a/tests/test_matplotlib_backend.py b/tests/test_matplotlib_backend.py new file mode 100644 index 0000000..af1d823 --- /dev/null +++ b/tests/test_matplotlib_backend.py @@ -0,0 +1,38 @@ +# Copyright (c) 2026. Jose M. Requena-Plens + +""" +Tests ensuring the package does not hijack the global matplotlib backend. + +Importing pyoctaveband must not force a specific (e.g. non-interactive) +backend, so the package can be used during interactive exploration +(IPython, Jupyter). See issue #52. +""" + +import os +import subprocess +import sys + + +def test_import_does_not_override_matplotlib_backend() -> None: + """Importing pyoctaveband must preserve the user's chosen backend.""" + code = ( + "import matplotlib\n" + # Pick an explicit, always-available backend the user might have set. + "matplotlib.use('svg')\n" + "before = matplotlib.get_backend()\n" + "import pyoctaveband\n" + "after = matplotlib.get_backend()\n" + "assert before == after, f'backend changed: {before!r} -> {after!r}'\n" + ) + # Propagate the parent's sys.path so the subprocess can import the package + # even when it is only on sys.path (e.g. pytest without an installed build). + env = os.environ.copy() + env["PYTHONPATH"] = os.pathsep.join(sys.path) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True, + env=env, + timeout=30, + ) + assert result.returncode == 0, result.stderr