Skip to content

fix: resolve python pytest warnings and deprecations#155

Open
seonghobae wants to merge 5 commits into
developfrom
fix/issue-153-warnings-deprecations
Open

fix: resolve python pytest warnings and deprecations#155
seonghobae wants to merge 5 commits into
developfrom
fix/issue-153-warnings-deprecations

Conversation

@seonghobae
Copy link
Copy Markdown
Owner

Summary

Resolves #154. This PR cleans up the pytest environment in services/analysis-engine so it runs with zero warnings:

  • Fixed RuntimeWarning for runpy.run_module in test_cli.py.
  • Fixed n_fft=1024 is too large for input signal warnings in test_chord_recognizer.py by generating 3.0-second synthetic signals instead of 1.0-second signals.
  • Addressed aifc, audioop, sunau deprecation warnings and audioread fallbacks in test_temporal.py by safely catching them and verifying file existence upfront.

Verification

  • export UV_PYTHON=3.12 && uv run pytest tests --cov=src/bandscope_analysis -W error passes successfully with 100% coverage and zero warnings.
  • Harness script (quickcheck.sh) passes.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 25, 2026

📝 Walkthrough

Summary by CodeRabbit

릴리스 노트

  • 버그 수정

    • 오디오 파일이 없을 때 더 명확한 오류 메시지 제공
    • 오디오 로딩 중 불필요한 경고 메시지 제거
  • 테스트

    • 코드 인식 테스트의 오디오 입력 길이 연장
    • 오류 처리에 대한 테스트 케이스 업데이트

Walkthrough

TemporalAnalyzer.analyze 메서드에 파일 존재 여부를 사전에 확인하는 로직과 librosa.load 호출 시 경고를 억제하는 기능이 추가되었습니다. 테스트는 오디오 입력 길이를 3배로 연장하고 예상 예외 타입을 수정했습니다.

Changes

Cohort / File(s) Summary
TemporalAnalyzer 메인 로직
services/analysis-engine/src/bandscope_analysis/temporal/analyzer.py
analyze 메서드에 파일 존재 여부 사전 확인(FileNotFoundError 발생) 및 librosa.load 호출 시 DeprecationWarning, FutureWarning 억제 기능 추가
Temporal 분석 테스트
services/analysis-engine/tests/test_temporal.py
파일 미존재 테스트 케이스의 예상 예외를 ValueError에서 FileNotFoundError로 변경
Chord 인식 테스트
services/analysis-engine/tests/test_chord_recognizer.py
모든 테스트 시나리오에서 오디오 입력 길이를 1초에서 3초로 확장 (endpoint=False, sr * 3 샘플 카운트 적용)

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

  • Issue #154: 테스트 스위트의 경고 및 Deprecation 메시지 해결 — librosaDeprecationWarningFutureWarning을 억제하는 변경사항이 이 이슈의 목표와 직접 연관됨

Possibly related PRs

  • PR #110: TemporalAnalyzer.analyze 함수의 동일한 부분을 수정하며 파일 존재 여부 확인 및 경고 억제 기능 구현과 관련

Poem

🐰 경고음 조용히 삼키고,
파일 찾아 미리 인사하고,
음성 길게 3배 늘려서,
더 정확한 분석을 위해
함께 나아가는 우리의 여정 🎵

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive PR 제목이 주요 변경사항과 부분적으로 관련되어 있으나, 가장 중요한 변경을 완전히 나타내지 못함. 제목을 더 구체적으로 변경 권고: 예를 들어 '파일 존재 확인 및 librosa 경고 억제' 같이 주요 코드 변경을 명확히 반영.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed PR 설명이 변경사항과 관련되어 있으며, 해결된 문제들과 검증 방법을 설명함.
Linked Issues check ✅ Passed 코드 변경이 연결된 이슈 #154의 요구사항을 충족: 파일 존재 확인, librosa 경고 억제, 신호 지속 시간 증가 등.
Out of Scope Changes check ✅ Passed 모든 변경사항이 경고 및 위험 제거라는 범위 내에 있음: 파일 검사, 신호 길이 조정, 경고 억제.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-153-warnings-deprecations

Comment @coderabbitai help to get the list of available commands and usage tips.

@seonghobae seonghobae marked this pull request as ready for review April 25, 2026 12:13
@seonghobae seonghobae enabled auto-merge April 25, 2026 12:13
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@services/analysis-engine/src/bandscope_analysis/temporal/analyzer.py`:
- Around line 39-40: Replace the Path(audio_path).exists() check with
Path(audio_path).is_file() to ensure only regular files (not directories or
special files) are accepted at the input boundary; keep raising
FileNotFoundError when the check fails but update the error message to reference
the actual input variable (audio_path) instead of path_str, and leave downstream
callers (e.g., librosa.load) to assume a verified file path.
- Around line 46-49: The current warnings.catch_warnings() block around the
librosa.load call ignores all DeprecationWarning/FutureWarning globally; narrow
this to only suppress warnings coming from audioread by replacing the
simplefilter calls with warnings.filterwarnings("ignore",
category=DeprecationWarning, module=r"^audioread") and
warnings.filterwarnings("ignore", category=FutureWarning, module=r"^audioread")
inside the same with warnings.catch_warnings(): context that surrounds the y, sr
= librosa.load(path_str, sr=TARGET_SR, mono=True) call so other
deprecation/future warnings still surface.

In `@services/analysis-engine/tests/test_chord_recognizer.py`:
- Line 50: Multiple tests create signals using repeated expressions like "y =
np.random.randn(22050 * 3)"; extract a shared constant or helper to compute
sample counts (e.g., SAMPLE_RATE = 22050 and DURATION_SECONDS = 3 or a helper
samples(seconds)) and replace all occurrences in the tests (references: variable
y initializations across test_chord_recognizer tests and any other tests that
build random signals) to use SAMPLE_RATE * DURATION_SECONDS or samples(3).
Update test setup/fixtures to import or define these constants/helpers so future
changes to sample rate or duration only require one edit.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5e9504e5-4480-4305-a01b-81504cac8dc1

📥 Commits

Reviewing files that changed from the base of the PR and between 425ad71 and 1721a4f.

📒 Files selected for processing (3)
  • services/analysis-engine/src/bandscope_analysis/temporal/analyzer.py
  • services/analysis-engine/tests/test_chord_recognizer.py
  • services/analysis-engine/tests/test_temporal.py

Comment on lines +39 to +40
if not Path(audio_path).exists():
raise FileNotFoundError(f"Audio file not found: {path_str}")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 목적: 파일 경계 검증 방식 점검 (exists vs is_file)
rg -n --type=py 'Path\(audio_path\)\.exists\(|\.is_file\(' services/analysis-engine/src/bandscope_analysis/temporal/analyzer.py

Repository: seonghobae/bandscope

Length of output: 109


🏁 Script executed:

cat -n services/analysis-engine/src/bandscope_analysis/temporal/analyzer.py | head -60

Repository: seonghobae/bandscope

Length of output: 2405


🏁 Script executed:

# Check the full function context around lines 39-40
sed -n '25,55p' services/analysis-engine/src/bandscope_analysis/temporal/analyzer.py

Repository: seonghobae/bandscope

Length of output: 1230


🏁 Script executed:

# Check if there are type hints or documentation
sed -n '1,50p' services/analysis-engine/src/bandscope_analysis/temporal/analyzer.py

Repository: seonghobae/bandscope

Length of output: 1499


🏁 Script executed:

# Check if there are similar validation patterns elsewhere in the file
rg -n 'Path.*\.(exists|is_file)\(' services/analysis-engine/src/bandscope_analysis/

Repository: seonghobae/bandscope

Length of output: 178


🏁 Script executed:

# Check if librosa.load is used elsewhere to see how errors are typically handled
rg -n 'librosa\.load' services/analysis-engine/src/bandscope_analysis/

Repository: seonghobae/bandscope

Length of output: 355


입력 경계에서 일반 파일 여부를 검증하도록 수정하세요.

Path.exists()는 디렉터리와 특수 파일도 True를 반환합니다. 현재 코드는 디렉터리를 통과시키면 librosa.load()에서 다른 예외가 발생하게 됩니다. 문서에서 "Path to the audio file"로 명시된 대로 입력 경계에서 정확히 일반 파일만 허용하도록 is_file()을 사용하세요.

제안 수정
-        path_str = str(audio_path)
-        if not Path(audio_path).exists():
+        path = Path(audio_path)
+        path_str = str(path)
+        if not path.is_file():
             raise FileNotFoundError(f"Audio file not found: {path_str}")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@services/analysis-engine/src/bandscope_analysis/temporal/analyzer.py` around
lines 39 - 40, Replace the Path(audio_path).exists() check with
Path(audio_path).is_file() to ensure only regular files (not directories or
special files) are accepted at the input boundary; keep raising
FileNotFoundError when the check fails but update the error message to reference
the actual input variable (audio_path) instead of path_str, and leave downstream
callers (e.g., librosa.load) to assume a verified file path.

Comment on lines +46 to +49
with warnings.catch_warnings():
warnings.simplefilter("ignore", category=DeprecationWarning)
warnings.simplefilter("ignore", category=FutureWarning)
y, sr = librosa.load(path_str, sr=TARGET_SR, mono=True)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 목적: 런타임 코드의 광범위 ignore 필터 존재 여부 확인
rg -n --type=py 'simplefilter\("ignore", category=(DeprecationWarning|FutureWarning)\)|filterwarnings\("ignore"' services/analysis-engine/src

Repository: seonghobae/bandscope

Length of output: 357


🏁 Script executed:

# 1. 전체 코드베이스에서 모든 경고 관련 필터/무시 패턴 검색
rg -n --type=py 'warnings\.(simplefilter|filterwarnings|catch_warnings)' services/analysis-engine/src

# 2. librosa 로드 주변의 전체 함수 컨텍스트 확인
rg -B 15 -A 5 'librosa\.load' services/analysis-engine/src/bandscope_analysis/temporal/analyzer.py

Repository: seonghobae/bandscope

Length of output: 1495


🏁 Script executed:

# 1. audioread이 프로젝트에서 사용되는지 확인
rg -n 'audioread' services/analysis-engine/src

# 2. 프로젝트 의존성 확인 (requirements, setup.py, pyproject.toml 등)
fd -t f '(requirements|setup|pyproject|poetry|pipfile)' services/analysis-engine/ | head -20

# 3. librosa 사용 패턴 확인
rg -n 'import librosa' services/analysis-engine/src

# 4. 코드에 경고 무시 이유에 대한 주석이 있는지 확인
rg -B 5 'catch_warnings' services/analysis-engine/src/bandscope_analysis/temporal/analyzer.py

Repository: seonghobae/bandscope

Length of output: 569


🏁 Script executed:

# pyproject.toml 내용 확인
cat services/analysis-engine/pyproject.toml | head -100

Repository: seonghobae/bandscope

Length of output: 850


librosa.load() 호출 시 특정 모듈로 경고 필터링 범위 좁히기

DeprecationWarning/FutureWarning 전체를 무시하면 라이브러리 업그레이드 시 호환성 문제를 조기에 탐지하기 어렵습니다. audioread(librosa의 음성 로드 백엔드)에서만 이 경고들을 무시하도록 범위를 좁혀주세요.

제안 수정
             with warnings.catch_warnings():
-                warnings.simplefilter("ignore", category=DeprecationWarning)
-                warnings.simplefilter("ignore", category=FutureWarning)
+                warnings.filterwarnings(
+                    "ignore",
+                    category=DeprecationWarning,
+                    module=r"audioread\..*",
+                )
+                warnings.filterwarnings(
+                    "ignore",
+                    category=FutureWarning,
+                    module=r"audioread\..*",
+                )
                 y, sr = librosa.load(path_str, sr=TARGET_SR, mono=True)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@services/analysis-engine/src/bandscope_analysis/temporal/analyzer.py` around
lines 46 - 49, The current warnings.catch_warnings() block around the
librosa.load call ignores all DeprecationWarning/FutureWarning globally; narrow
this to only suppress warnings coming from audioread by replacing the
simplefilter calls with warnings.filterwarnings("ignore",
category=DeprecationWarning, module=r"^audioread") and
warnings.filterwarnings("ignore", category=FutureWarning, module=r"^audioread")
inside the same with warnings.catch_warnings(): context that surrounds the y, sr
= librosa.load(path_str, sr=TARGET_SR, mono=True) call so other
deprecation/future warnings still surface.

"""Test for test_chord_recognizer_hpss_exception."""
recognizer = ChordRecognizer()
y = np.random.randn(22050)
y = np.random.randn(22050 * 3)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

반복되는 샘플 수 계산은 상수/헬퍼로 통일하는 것이 좋습니다.

현재 패턴이 여러 테스트에 반복되어, 샘플링 레이트나 길이 변경 시 수정 지점이 많아집니다. 공통 상수/헬퍼로 추출하면 유지보수성이 좋아집니다.

예시 리팩터링 diff
 import numpy as np

 from bandscope_analysis.chords.chord_recognizer import ChordRecognizer

+SR = 22050
+DURATION_SEC = 3
+
+
+def _noise_signal(sr: int = SR, duration_sec: int = DURATION_SEC) -> np.ndarray:
+    return np.random.randn(sr * duration_sec)

@@
 def test_chord_recognizer_hpss_exception():
@@
-    y = np.random.randn(22050 * 3)
+    y = _noise_signal()

@@
 def test_chord_recognizer_chroma_cqt_exception():
@@
-    y = np.random.randn(22050 * 3)
+    y = _noise_signal()

@@
 def test_chord_recognizer_rms_exception():
@@
-    y = np.random.randn(22050 * 3)
+    y = _noise_signal()

@@
 def test_chord_recognizer_rms_padding():
@@
-    y = np.random.randn(22050 * 3)
+    y = _noise_signal()

@@
 def test_chord_recognizer_empty_chromagram():
@@
-    y = np.random.randn(22050 * 3)
+    y = _noise_signal()

@@
 def test_chord_recognizer_rms_longer():
@@
-    y = np.random.randn(22050 * 3)
+    y = _noise_signal()

Also applies to: 60-60, 70-70, 80-80, 94-94, 105-105

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@services/analysis-engine/tests/test_chord_recognizer.py` at line 50, Multiple
tests create signals using repeated expressions like "y = np.random.randn(22050
* 3)"; extract a shared constant or helper to compute sample counts (e.g.,
SAMPLE_RATE = 22050 and DURATION_SECONDS = 3 or a helper samples(seconds)) and
replace all occurrences in the tests (references: variable y initializations
across test_chord_recognizer tests and any other tests that build random
signals) to use SAMPLE_RATE * DURATION_SECONDS or samples(3). Update test
setup/fixtures to import or define these constants/helpers so future changes to
sample rate or duration only require one edit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix warnings and deprecation messages in test suite

1 participant