Catches the silent excepts the awk-based earlier sweeps missed:
- Bare `except:` followed by `pass` (also swallows KeyboardInterrupt
and SystemExit — actively wrong). Upgraded to `except Exception as
e: logger.debug("...: %s", e)`. ~14 sites across connection_detect,
soulseek_client, listenbrainz_manager, watchlist_scanner,
youtube_client, navidrome_client, jellyfin_client, web_server.
- `except Exception:` + pass that the awk pattern missed (e.g.
multi-line or unusual whitespace). ~31 sites across automation_engine,
database_update_worker, music_database, spotify_client, web_server,
others.
- 14 legitimate cleanup sites left silent with explicit `# noqa: S110`
+ comment explaining why (atexit handlers, finally-block conn.close
calls). Logging during shutdown can itself crash because file handles
get torn down before the handler fires.
Also enables `S110` rule in pyproject.toml so this pattern fails CI
going forward — drift fails at PR review instead of at runtime against
a wedged worker thread. Tests path keeps S110 ignored (test fixtures
legitimately use try-except-pass for cleanup).
Adds a WHATS_NEW entry to helper.js summarizing the full #369 sweep.
Verified: `python -m ruff check .` → All checks passed.
Verified: `python -m pytest tests/` → 2188 passed.
Closes#369
PR #340 added ruff to the build-and-test.yml CI gate, which surfaced
286 pre-existing lint errors. Left unfixed, every feature branch push
fails CI. This commit resolves all of them so CI goes green and
contributors can actually land work.
Auto-fixes (248 of 286): removed unused f-string prefixes (F541),
renamed unused loop control variables with underscore prefix (B007),
removed duplicate imports (F811).
Manually fixed 10 latent bugs ruff caught (all wrapped in try/except
today, silently failing):
- music_database.py: _add_discovery_tables() called undefined
conn.commit() — would have crashed the iTunes-support migration
for existing databases. Now uses cursor.connection.commit().
- web_server.py settings GET: referenced undefined download_orchestrator
when it should be soulseek_client. Feature (_source_status on the
settings payload) was silently missing for UI auto-disable logic.
- web_server.py _process_wishlist_automatically: active_server
undefined in track-ownership check. Auto-wishlist was falling
through to the error handler and re-downloading owned tracks.
- web_server.py start_wishlist_missing_downloads: same active_server
bug in the manual wishlist path.
- web_server.py _process_failed_tracks_to_wishlist_exact: emitted
wishlist_item_added automation event with undefined artist_name
and track. Automation event silently never fired correctly.
- web_server.py discovery metadata enrichment: referenced cache
without calling get_metadata_cache() first. Track enrichment from
cached API responses was silently skipped.
- web_server.py Beatport discovery worker: wing-it fallback branch
used undefined successful_discoveries variable. Wing-it counter
never incremented correctly. Now uses state['spotify_matches']
consistently with the rest of the function.
- web_server.py _run_full_missing_tracks_process: stale import json
mid-function shadowed the module-level import, making an earlier
json.dumps() call reference an unbound local (F823).
- web_server.py discovery loop: platform loop variable shadowed
the module-level platform import (F402).
- core/watchlist_scanner.py: 7 lambda captures of loop variables
(B023 classic Python closure-in-loop bug) now bind at creation.
No existing tests had to change. Full suite stays at 263 passed.
web_server.py is already doing some logging with the scraped data, so we don't necessarily need to include the scraper's own logs in the output.
A new env variable was added to make it possible to surface the scraper's logs if needed, but it's expected that the web server's own logging should be sufficient here
Stripped 4,200+ emoji characters from print(), logger calls across
39 Python files. Logs are now clean text — easier to grep, more
professional, no encoding issues on terminals without Unicode support.
Seasonal config icons preserved for UI display.
- Fix enrichment progress never updating: remove `continue` that skipped
progress_callback for successful tracks in enrich_chart_tracks
- Split chart/extract into two-step flow: extract raw tracks, then enrich
via polling endpoint with live progress overlay updates
- Move Beatport enrichment cache to persistent metadata cache system
- Fix metadata cache detail modal for Beatport (URL entity_ids with slashes)
- Add per-source Clear dropdown (Spotify/iTunes/Deezer/Beatport) to cache browser
- Remove debug logging from enrichment progress tracking
Clicking any Beatport item now opens the download modal directly instead of
going through the discovery flow (scrape → chart card → discovery modal →
Spotify/iTunes matching → download).
Releases (albums/EPs) open as album downloads with full context.
Charts/playlists (Top 100, Featured Charts, DJ Charts, Top 10) open as
playlist downloads with per-track enrichment — each track's individual
Beatport page is visited to get release name, duration, artwork, BPM, key,
genre, and label.
Key changes:
- Add get_release_metadata() and enrich_chart_tracks() to scraper
- Add /api/beatport/release-metadata and /api/beatport/enrich-tracks endpoints
- Rewrite all Beatport click handlers to open download modal directly
- Per-track enrichment with live progress overlay (one-by-one fetching)
- Split combined artist strings so folder paths use primary artist only
- Prevent Beatport IDs from being written to Spotify tag fields
- Add beatport_release_ prefix detection for album download mode
- Support enrich=false query param for frontend-driven enrichment
Replace all hardcoded styled-components class selectors (with build hashes
that break on every Beatport deploy) with partial class name matches using
[class*="prefix"] pattern. Applies to new releases endpoint and hero
release scraper.
Introduces backend scraping and API endpoint for Beatport genre Top 10 and Hype Top 10 tracks, with 1-hour caching. Updates frontend to load and display these lists in the genre browser modal, matching main page structure and click handling for chart discovery.
Introduces text cleaning for track, artist, and label fields in both Python and JS to ensure proper spacing and formatting. Adds logic to the frontend for handling Beatport Top 10 and Hype Top 10 containers on the rebuild page, including DOM extraction and card creation, following the Browse Charts pattern.