Problem
Genius lyrics contain section headers like [Verse 2: Drake] with artist attribution, but processor.py strips these without parsing. Featured artist vocals are counted as primary artist vocabulary.
Additionally, remove_section_headers=True in GeniusClient.__init__() causes lyricsgenius to strip headers before BarScan can parse them.
Proposed Changes
src/barscan/genius/client.py
- Change
remove_section_headers=True to False (line 64) - BarScan's clean_lyrics() already handles removal
New file: src/barscan/analyzer/sections.py
SectionHeader model (frozen): section_type, artist_name: str | None, raw
SECTION_HEADER_WITH_ARTIST_PATTERN = re.compile(r"\[([^\]:]+?)(?::\s*(.+?))?\]")
parse_section_header(), extract_section_headers()
is_artist_match() - case-insensitive substring matching, unknown artists default to inclusion
filter_lyrics_by_artist() - keeps primary artist sections and unlabeled sections
src/barscan/analyzer/models.py
- Add
filter_featured_sections: bool = Field(default=False) to AnalysisConfig
src/barscan/analyzer/processor.py
- Add
primary_artist and featured_artists params to preprocess()
- Call
filter_lyrics_by_artist() before clean_lyrics() when config enables it
src/barscan/analyzer/frequency.py
- Add
primary_artist and featured_artists params to analyze_text(), pass through to preprocess()
src/barscan/cli.py
- Add
--filter-featured option (default off)
- Pass
primary_artist=artist_data.artist.name to analyze_text()
Tests
- New
tests/test_analyzer/test_sections.py: header parsing, artist matching, lyrics filtering
tests/test_analyzer/test_processor.py: preprocess with filtering
tests/test_cli/test_commands.py: --filter-featured flag
Considerations
- Section header format varies (community-edited on Genius)
- Japanese headers supported (e.g.,
[1番: KOHH])
- Best-effort, not guaranteed
Dependencies
No dependency on Issue 1 (independent feature).
Problem
Genius lyrics contain section headers like
[Verse 2: Drake]with artist attribution, butprocessor.pystrips these without parsing. Featured artist vocals are counted as primary artist vocabulary.Additionally,
remove_section_headers=TrueinGeniusClient.__init__()causes lyricsgenius to strip headers before BarScan can parse them.Proposed Changes
src/barscan/genius/client.pyremove_section_headers=TruetoFalse(line 64) - BarScan'sclean_lyrics()already handles removalNew file:
src/barscan/analyzer/sections.pySectionHeadermodel (frozen):section_type,artist_name: str | None,rawSECTION_HEADER_WITH_ARTIST_PATTERN = re.compile(r"\[([^\]:]+?)(?::\s*(.+?))?\]")parse_section_header(),extract_section_headers()is_artist_match()- case-insensitive substring matching, unknown artists default to inclusionfilter_lyrics_by_artist()- keeps primary artist sections and unlabeled sectionssrc/barscan/analyzer/models.pyfilter_featured_sections: bool = Field(default=False)toAnalysisConfigsrc/barscan/analyzer/processor.pyprimary_artistandfeatured_artistsparams topreprocess()filter_lyrics_by_artist()beforeclean_lyrics()when config enables itsrc/barscan/analyzer/frequency.pyprimary_artistandfeatured_artistsparams toanalyze_text(), pass through topreprocess()src/barscan/cli.py--filter-featuredoption (default off)primary_artist=artist_data.artist.nametoanalyze_text()Tests
tests/test_analyzer/test_sections.py: header parsing, artist matching, lyrics filteringtests/test_analyzer/test_processor.py: preprocess with filteringtests/test_cli/test_commands.py:--filter-featuredflagConsiderations
[1番: KOHH])Dependencies
No dependency on Issue 1 (independent feature).