[READ-ONLY] Mirror of https://github.com/jmrplens/PyOctaveBand. [Python3] Octave-Band and Fractional Octave-Band filter. For signal in time domain. jmrplens.github.io/PyOctaveBand/
acoustics audio filter frequency frequency-analysis frequency-domain octave python3 signal time-domain
0

Configure Feed

Select the types of activity you want to include in your feed.

Restore the _plotting compatibility re-exports lost in the lint modernization (#351)

The ruff 0.16 adoption applied the PLC0414 and F401 unsafe fixes to
src/phonometry/_plotting.py and deleted all 82 redundant-alias re-exports,
leaving only the docstring. The module is documented as a silent re-export
of the plot renderers (moved to phonometry._plot) for one deprecation
cycle, so from phonometry._plotting import plot_impulse_response and every
sibling raised ImportError. The sibling shim scripts/fdtd2d.py got the
explicit __all__ treatment in the same commit; this one was missed.

Bring back all 82 re-exports as grouped plain imports per source module
and declare an explicit __all__ so the lint fixers keep them (every target
still exists in phonometry._plot, none dropped). Keep the module out of
_compat._MOVED on purpose: that table maps one old path to one relocated
module and warns on attribute access, while _plotting fans out to thirteen
domain modules and is documented as silent.

Harden tests/test_deprecated_aliases.py so this cannot regress silently:
every pre-move module path must now expose a non-empty public surface, and
a new test pins the frozen 82-name _plotting re-export snapshot, asserting
__all__ matches and each name resolves to a callable without warnings.

authored by

José M. Requena Plens and committed by
GitHub
(Jul 25, 2026, 2:47 AM +0200) 8e971c8b f55628d9

+306
+7
CHANGELOG.md
··· 7 7 8 8 ## [Unreleased] 9 9 10 + ### Fixed 11 + 12 + - Restore the `phonometry._plotting` compatibility re-exports that were lost 13 + during the lint modernization: the module is again a silent re-export of 14 + every plot renderer moved to `phonometry._plot` (kept for one deprecation 15 + cycle, removed in 4.0), now with an explicit `__all__` so the lint fixers 16 + keep it, and the deprecation test suite asserts the full re-export surface. 10 17 11 18 ### Changed 12 19
+193
src/phonometry/_plotting.py
··· 8 8 9 9 from __future__ import annotations 10 10 11 + from ._plot.aircraft import ( 12 + plot_aircraft_band_attenuation, 13 + plot_epnl, 14 + plot_flyover, 15 + plot_noise_contour, 16 + plot_npd_level, 17 + plot_rotorcraft_hemisphere, 18 + ) 19 + from ._plot.building import ( 20 + plot_airborne_insulation, 21 + plot_airborne_prediction, 22 + plot_band_uncertainty, 23 + plot_facade_insulation, 24 + plot_facade_prediction, 25 + plot_floor_covering_improvement, 26 + plot_impact_insulation, 27 + plot_impact_prediction, 28 + plot_impact_rating, 29 + plot_installed_structure_borne, 30 + plot_radiated_power, 31 + plot_structure_borne_power, 32 + plot_vibration_reduction, 33 + plot_weighted_rating, 34 + ) 35 + from ._plot.electroacoustics import ( 36 + plot_frequency_response, 37 + plot_harmonic_distortion, 38 + ) 39 + from ._plot.emission import ( 40 + plot_intensity, 41 + plot_sound_power, 42 + plot_vibration_sound_power, 43 + ) 44 + from ._plot.environmental import ( 45 + plot_impulse_prominence, 46 + plot_outdoor_attenuation, 47 + plot_tonal_adjustment, 48 + plot_wind_turbine_tonality, 49 + ) 50 + from ._plot.hearing import ( 51 + plot_age_threshold, 52 + plot_htlan, 53 + plot_nipts, 54 + plot_occupational_exposure, 55 + plot_sii, 56 + plot_sti, 57 + ) 58 + from ._plot.materials import ( 59 + plot_absorption_uncertainty, 60 + plot_diffusion_polar, 61 + plot_dynamic_stiffness, 62 + plot_impedance_tube, 63 + plot_insitu_absorption, 64 + plot_scattering_coefficient, 65 + plot_static_airflow, 66 + plot_weighted_absorption, 67 + ) 68 + from ._plot.metrology import ( 69 + plot_monte_carlo, 70 + plot_uncertainty_budget, 71 + ) 72 + from ._plot.psychoacoustics import ( 73 + plot_ecma_loudness, 74 + plot_ecma_roughness, 75 + plot_ecma_tonality, 76 + plot_fluctuation_strength, 77 + plot_moore_glasberg_loudness, 78 + plot_moore_glasberg_time_loudness, 79 + plot_psychoacoustic_annoyance, 80 + plot_tone_audibility, 81 + plot_zwicker_loudness, 82 + ) 83 + from ._plot.room import ( 84 + plot_decay_curve, 85 + plot_enclosed_space_absorption, 86 + plot_excitation, 87 + plot_impulse_response, 88 + plot_noise_criterion, 89 + plot_open_plan, 90 + plot_reverberation_models, 91 + plot_room_acoustics, 92 + plot_room_criterion, 93 + ) 94 + from ._plot.simulation import ( 95 + plot_fdtd_probes, 96 + plot_fdtd_snapshot, 97 + ) 98 + from ._plot.underwater import ( 99 + plot_ambient_noise, 100 + plot_bottom_loss, 101 + plot_normal_modes, 102 + plot_parabolic_equation, 103 + plot_pile_strike, 104 + plot_ray_trace, 105 + plot_ship_source_level, 106 + plot_ship_traffic_spectrum, 107 + plot_sonar_equation, 108 + plot_sound_speed_profile, 109 + plot_transmission_loss, 110 + ) 111 + from ._plot.vibration import ( 112 + plot_daily_exposure, 113 + plot_mobility, 114 + plot_multiple_shock, 115 + plot_transfer_stiffness, 116 + plot_vibration_weighting, 117 + plot_weighted_spectrum, 118 + ) 119 + 120 + __all__ = [ 121 + "plot_absorption_uncertainty", 122 + "plot_age_threshold", 123 + "plot_airborne_insulation", 124 + "plot_airborne_prediction", 125 + "plot_aircraft_band_attenuation", 126 + "plot_ambient_noise", 127 + "plot_band_uncertainty", 128 + "plot_bottom_loss", 129 + "plot_daily_exposure", 130 + "plot_decay_curve", 131 + "plot_diffusion_polar", 132 + "plot_dynamic_stiffness", 133 + "plot_ecma_loudness", 134 + "plot_ecma_roughness", 135 + "plot_ecma_tonality", 136 + "plot_enclosed_space_absorption", 137 + "plot_epnl", 138 + "plot_excitation", 139 + "plot_facade_insulation", 140 + "plot_facade_prediction", 141 + "plot_fdtd_probes", 142 + "plot_fdtd_snapshot", 143 + "plot_floor_covering_improvement", 144 + "plot_fluctuation_strength", 145 + "plot_flyover", 146 + "plot_frequency_response", 147 + "plot_harmonic_distortion", 148 + "plot_htlan", 149 + "plot_impact_insulation", 150 + "plot_impact_prediction", 151 + "plot_impact_rating", 152 + "plot_impedance_tube", 153 + "plot_impulse_prominence", 154 + "plot_impulse_response", 155 + "plot_insitu_absorption", 156 + "plot_installed_structure_borne", 157 + "plot_intensity", 158 + "plot_mobility", 159 + "plot_monte_carlo", 160 + "plot_moore_glasberg_loudness", 161 + "plot_moore_glasberg_time_loudness", 162 + "plot_multiple_shock", 163 + "plot_nipts", 164 + "plot_noise_contour", 165 + "plot_noise_criterion", 166 + "plot_normal_modes", 167 + "plot_npd_level", 168 + "plot_occupational_exposure", 169 + "plot_open_plan", 170 + "plot_outdoor_attenuation", 171 + "plot_parabolic_equation", 172 + "plot_pile_strike", 173 + "plot_psychoacoustic_annoyance", 174 + "plot_radiated_power", 175 + "plot_ray_trace", 176 + "plot_reverberation_models", 177 + "plot_room_acoustics", 178 + "plot_room_criterion", 179 + "plot_rotorcraft_hemisphere", 180 + "plot_scattering_coefficient", 181 + "plot_ship_source_level", 182 + "plot_ship_traffic_spectrum", 183 + "plot_sii", 184 + "plot_sonar_equation", 185 + "plot_sound_power", 186 + "plot_sound_speed_profile", 187 + "plot_static_airflow", 188 + "plot_sti", 189 + "plot_structure_borne_power", 190 + "plot_tonal_adjustment", 191 + "plot_tone_audibility", 192 + "plot_transfer_stiffness", 193 + "plot_transmission_loss", 194 + "plot_uncertainty_budget", 195 + "plot_vibration_reduction", 196 + "plot_vibration_sound_power", 197 + "plot_vibration_weighting", 198 + "plot_weighted_absorption", 199 + "plot_weighted_rating", 200 + "plot_weighted_spectrum", 201 + "plot_wind_turbine_tonality", 202 + "plot_zwicker_loudness", 203 + ]
+106
tests/test_deprecated_aliases.py
··· 384 384 warnings.simplefilter("error", DeprecationWarning) 385 385 module = importlib.import_module(path) # import itself must be silent 386 386 assert module is sys.modules[path] 387 + # A shim that imports but exposes nothing is as broken as an ImportError: 388 + # every pre-move path must still surface its public names. ``dir()`` is 389 + # silent on the PEP 562 shims, so this stays warning-free. 390 + public = [name for name in dir(module) if not name.startswith("_")] 391 + assert public, f"{path} imports but exposes no public names" 392 + 393 + 394 + # Frozen snapshot of the ``phonometry._plotting`` re-export surface (the 395 + # renderers as of the 3.2 move); do NOT regenerate from the live tree. 396 + _PLOTTING_RENDERERS = [ 397 + "plot_absorption_uncertainty", 398 + "plot_age_threshold", 399 + "plot_airborne_insulation", 400 + "plot_airborne_prediction", 401 + "plot_aircraft_band_attenuation", 402 + "plot_ambient_noise", 403 + "plot_band_uncertainty", 404 + "plot_bottom_loss", 405 + "plot_daily_exposure", 406 + "plot_decay_curve", 407 + "plot_diffusion_polar", 408 + "plot_dynamic_stiffness", 409 + "plot_ecma_loudness", 410 + "plot_ecma_roughness", 411 + "plot_ecma_tonality", 412 + "plot_enclosed_space_absorption", 413 + "plot_epnl", 414 + "plot_excitation", 415 + "plot_facade_insulation", 416 + "plot_facade_prediction", 417 + "plot_fdtd_probes", 418 + "plot_fdtd_snapshot", 419 + "plot_floor_covering_improvement", 420 + "plot_fluctuation_strength", 421 + "plot_flyover", 422 + "plot_frequency_response", 423 + "plot_harmonic_distortion", 424 + "plot_htlan", 425 + "plot_impact_insulation", 426 + "plot_impact_prediction", 427 + "plot_impact_rating", 428 + "plot_impedance_tube", 429 + "plot_impulse_prominence", 430 + "plot_impulse_response", 431 + "plot_insitu_absorption", 432 + "plot_installed_structure_borne", 433 + "plot_intensity", 434 + "plot_mobility", 435 + "plot_monte_carlo", 436 + "plot_moore_glasberg_loudness", 437 + "plot_moore_glasberg_time_loudness", 438 + "plot_multiple_shock", 439 + "plot_nipts", 440 + "plot_noise_contour", 441 + "plot_noise_criterion", 442 + "plot_normal_modes", 443 + "plot_npd_level", 444 + "plot_occupational_exposure", 445 + "plot_open_plan", 446 + "plot_outdoor_attenuation", 447 + "plot_parabolic_equation", 448 + "plot_pile_strike", 449 + "plot_psychoacoustic_annoyance", 450 + "plot_radiated_power", 451 + "plot_ray_trace", 452 + "plot_reverberation_models", 453 + "plot_room_acoustics", 454 + "plot_room_criterion", 455 + "plot_rotorcraft_hemisphere", 456 + "plot_scattering_coefficient", 457 + "plot_ship_source_level", 458 + "plot_ship_traffic_spectrum", 459 + "plot_sii", 460 + "plot_sonar_equation", 461 + "plot_sound_power", 462 + "plot_sound_speed_profile", 463 + "plot_static_airflow", 464 + "plot_sti", 465 + "plot_structure_borne_power", 466 + "plot_tonal_adjustment", 467 + "plot_tone_audibility", 468 + "plot_transfer_stiffness", 469 + "plot_transmission_loss", 470 + "plot_uncertainty_budget", 471 + "plot_vibration_reduction", 472 + "plot_vibration_sound_power", 473 + "plot_vibration_weighting", 474 + "plot_weighted_absorption", 475 + "plot_weighted_rating", 476 + "plot_weighted_spectrum", 477 + "plot_wind_turbine_tonality", 478 + "plot_zwicker_loudness", 479 + ] 480 + 481 + 482 + def test_plotting_shim_re_exports_every_renderer() -> None: 483 + """``phonometry._plotting`` silently re-exports the full renderer set.""" 484 + import importlib 485 + import warnings 486 + 487 + with warnings.catch_warnings(): 488 + warnings.simplefilter("error", DeprecationWarning) 489 + module = importlib.import_module("phonometry._plotting") 490 + assert sorted(module.__all__) == _PLOTTING_RENDERERS 491 + for name in _PLOTTING_RENDERERS: 492 + assert callable(getattr(module, name)), name 387 493 388 494 389 495 def test_moved_module_shims_warn_and_delegate() -> None: