Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions src/pyoctaveband/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

from typing import List, Tuple, overload, Literal

import matplotlib
import numpy as np

from .calibration import calculate_sensitivity
Expand All @@ -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__",
Expand Down
2 changes: 1 addition & 1 deletion src/pyoctaveband/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "1.2.2"
__version__ = "1.2.3"
7 changes: 7 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
38 changes: 38 additions & 0 deletions tests/test_matplotlib_backend.py
Original file line number Diff line number Diff line change
@@ -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,
)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
assert result.returncode == 0, result.stderr
Comment on lines +12 to +38

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The subprocess is executed without propagating the current sys.path or setting PYTHONPATH. If the package is not installed in the environment (for example, when running tests locally via pytest where the path is dynamically added to sys.path), the subprocess will fail with ModuleNotFoundError: No module named 'pyoctaveband'.

To ensure the test is robust across different test runners and environments, pass the parent process's sys.path via the PYTHONPATH environment variable to the subprocess.

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"
    )
    env = os.environ.copy()
    env["PYTHONPATH"] = os.path.pathsep.join(sys.path)
    result = subprocess.run(
        [sys.executable, "-c", code],
        capture_output=True,
        text=True,
        env=env,
    )
    assert result.returncode == 0, result.stderr

Loading