In the fetch_text method (line ~207):
if not r.encoding:
r.encoding = "utf-8" # ← Double quotes!
In the scrape method, make sure there are 2 blank lines before the next class:
return None
class Tekstowo(SearchBackend): # ← Two blank lines above
That should pass the formatting check! The repo follows PEP 8 style (double quotes, 2 blank lines between classes).
## Key Improvements (addressing reviewer feedback):
- ✅ Uses regex instead of while loop (more efficient, one pass)
- ✅ No infinite loop risk
- ✅ Handles any number of backslashes before quotes
- ✅ Clear inline comments
## Problem
The lyrics plugin has two bugs that corrupt fetched lyrics:
1. **Unicode corruption**: Characters like `ò`, `è`, `à` are corrupted to `√≤`, `√®`, etc.
2. **Escaped quotes**: Quotes appear as `\"` instead of `"` in lyrics
## Root Causes
### Issue 1: MacRoman encoding misdetection
- **Location**: `RequestHandler.fetch_text()` line 220
- **Cause**: Setting `r.encoding = None` forces requests to use `apparent_encoding`
- **Problem**: For Genius.com (and others), requests incorrectly detects MacRoman instead of UTF-8
- **Result**: UTF-8 bytes `c3 b2` (ò) decoded as MacRoman produces "√≤" (U+221A U+2264)
### Issue 2: Incomplete JSON unescape
- **Location**: `Genius.scrape()` line 576
- **Cause**: The `remove_backslash` regex doesn't handle all escape patterns in JSON
- **Problem**: Genius embeds lyrics in JSON with patterns like `\\"` and `\\\\"`
- **Result**: After BeautifulSoup processing, escaped quotes remain in final text
## Solution
### Fix 1: Trust server encoding, fallback to UTF-8
```python
# OLD: r.encoding = None
# NEW:
if not r.encoding:
r.encoding = 'utf-8'
```
- Respects server's declared encoding (UTF-8 for Genius)
- Falls back to UTF-8 if no encoding specified (safer than apparent_encoding)
- Preserves original intent of handling misconfigured servers
### Fix 2: Iteratively clean escaped quotes
```python
while '\\"' in lyrics:
lyrics = lyrics.replace('\\"', '"')
```
- Handles variable escape levels (`\"`, `\\\"`, `\\\\\"`)
- Minimal change - keeps original `remove_backslash` regex
- Applied after BeautifulSoup to avoid interfering with HTML parsing
## Testing
Tested with:
- Caparezza - "Argenti Vive" (Italian, many accented characters)
- WestsideGunn - "Heel Cena" (escaped quotes in lyrics)
Before:
```
mi si parò davanti
\\"I got big moves\\"
```
After:
```
mi si parò davanti
"I got big moves"
```
## Impact
- Fixes lyrics for all languages with non-ASCII characters
- Fixes Genius lyrics with quotes
- No breaking changes - maintains backward compatibility
- Minimal code changes (14 lines total)
See this line in https://musicbrainz.org/doc/MusicBrainz_API#Lookups
> To include more than one subquery in a single request, separate the arguments to inc= with a + (plus sign), like inc=recordings+labels.
Introduce a new RequestHandler base class to introduce a shared session,
centralize HTTP request management and error handling across plugins.
Key changes:
- Add RequestHandler base class with a shared/cached session
- Convert TimeoutSession to use SingletonMeta for proper resource
management
- Create LyricsRequestHandler subclass with lyrics-specific error
handling
- Update MusicBrainzAPI to inherit from RequestHandler
## Description
Fixes#5625
When `convert.never_convert_lossy_files` is enabled, `beet convert` was
ignoring the explicit `--format` option and just copying the lossy files
without
transcoding them. For example:
- `beet convert format:mp3 --format opus`
would still produce MP3 files instead of OPUS.
Change:
- Allows to override options `never_convert_lossy_files`, `max_bitrate`
or `no_convert` for `beet convert` as well as trying to convert to the
same format as existing already with a new option `--force`. That way,
for example lossy files selected by the query are transcoded to the
requested format anyway.
- Keeps existing behavior for automatic conversion on import (no CLI
override there).
- Adds tests to cover checking whether `--force` correctly overrides
settings or CLI options.
- Documents the behavior in the convert plugin docs
Co-authored-by: J0J0 Todos <jojo@peek-a-boo.at>
This plugin aims to address the shortcomings of the %title function, as
brought up in issues #152, #3298 and an initial look to improvement with
#3411. It supplies a new string format command, `%titlecase` which
doesn't interfere with any prior expected behavior of the `%title`
format command.
It also adds the ability to apply titlecase logic to metadata fields
that a user selects, which is useful if you, like me, are looking for
stylistic consistency and the minor stylistic differences between
Musizbrainz, Discogs, Deezer etc, with title case are slightly
infuriating.
This will add an optional dependency of
[titlecase](https://pypi.org/project/titlecase/), which allows the
titlecase core logic to be externally maintained.
If there's not enough draw to have this as a core plugin, I can also
spin this into an independent one, but it seemed like a recurring theme
that the %title string format didn't really behave as expected, and I
wanted my metadata to match too.
- [x] Documentation. (If you've added a new command-line flag, for
example, find the appropriate page under `docs/` to describe it.)
- [x] Changelog. (Add an entry to `docs/changelog.rst` to the bottom of
one of the lists near the top of the document.)
- [x] Tests. - Not 100% coverage, but didn't see a lot of other plugins
with testing for import stages.