Repository Analysis

spotDL/spotify-downloader

Download your Spotify playlists and songs along with album art and metadata (from YouTube if a match is found).

5.5 Low AI signal View on GitHub
5.5
Adjusted Score
5.5
Raw Score
100%
Time Factor
2026-05-19
Last Push
24,971
Stars
Python
Language
47,392
Lines of Code
139
Files
167
Pattern Hits
2026-05-31
Scan Date

Score History

Severity Breakdown

CRITICAL 0HIGH 14MEDIUM 14LOW 139

Pattern Findings

167 matches across 9 categories. Click a row to expand file-level details.

Cross-File Repetition13 hits · 65 pts
SeverityFileLineSnippet
HIGHspotdl/providers/lyrics/genius.py0returns the results for the given song. ### arguments - name: the name of the song. - artists: the artists of the song.
HIGHspotdl/providers/lyrics/musixmatch.py0returns the results for the given song. ### arguments - name: the name of the song. - artists: the artists of the song.
HIGHspotdl/providers/lyrics/synced.py0returns the results for the given song. ### arguments - name: the name of the song. - artists: the artists of the song.
HIGHspotdl/providers/lyrics/base.py0returns the results for the given song. ### arguments - name: the name of the song. - artists: the artists of the song.
HIGHspotdl/providers/lyrics/azlyrics.py0returns the results for the given song. ### arguments - name: the name of the song. - artists: the artists of the song.
HIGHspotdl/providers/lyrics/genius.py0extracts the lyrics from the given url. ### arguments - url: the url to extract the lyrics from. - kwargs: additional ar
HIGHspotdl/providers/lyrics/musixmatch.py0extracts the lyrics from the given url. ### arguments - url: the url to extract the lyrics from. - kwargs: additional ar
HIGHspotdl/providers/lyrics/synced.py0extracts the lyrics from the given url. ### arguments - url: the url to extract the lyrics from. - kwargs: additional ar
HIGHspotdl/providers/lyrics/base.py0extracts the lyrics from the given url. ### arguments - url: the url to extract the lyrics from. - kwargs: additional ar
HIGHspotdl/providers/lyrics/azlyrics.py0extracts the lyrics from the given url. ### arguments - url: the url to extract the lyrics from. - kwargs: additional ar
HIGHspotdl/providers/audio/bandcamp.py0get results from slider.kz ### arguments - search_term: the search term to search for. - args: unused. - kwargs: unused.
HIGHspotdl/providers/audio/sliderkz.py0get results from slider.kz ### arguments - search_term: the search term to search for. - args: unused. - kwargs: unused.
HIGHspotdl/providers/audio/soundcloud.py0get results from slider.kz ### arguments - search_term: the search term to search for. - args: unused. - kwargs: unused.
Hyper-Verbose Identifiers45 hits · 44 pts
SeverityFileLineSnippet
LOWtests/conftest.py76def fake_create_subprocess_exec(*args, stdout=None, stderr=None, **kwargs):
LOWtests/types/test_song.py112# def test_song_from_search_term():
LOWtests/types/test_song.py197def test_song_from_data_dump_wrong_type():
LOWtests/types/test_playlist.py30def test_playlist_wrong_initget_results():
LOWtests/types/test_playlist.py61def test_playlist_from_string():
LOWtests/providers/lyrics/test_musixmatch.py7# def test_get_musixmatch_lyrics():
LOWtests/providers/audio/test_youtube.py84def test_yt_get_results_normalizes_null_metadata(mocker):
LOWtests/providers/audio/test_ytmusic.py54def test_ytm_get_results_retries_with_new_client(mocker):
LOWtests/utils/test_logging.py8def test_spotdl_formatter_format():
LOWtests/utils/test_github.py35def test_check_for_updates_fail(monkeypatch):
LOWtests/utils/test_formatter.py104def test_create_file_name_restrict():
LOWtests/utils/test_config.py51def test_get_config_not_created(setup):
LOWtests/utils/test_config.py60def test_use_official_api_default():
LOWtests/utils/test_config.py70def test_use_official_api_from_config():
LOWtests/utils/test_config.py84def test_use_official_api_argument_overrides_config():
LOWtests/utils/test_ffmpeg.py29def test_is_not_ffmpeg_installed(monkeypatch):
LOWtests/utils/test_ffmpeg.py42def test_get_none_ffmpeg_path(monkeypatch):
LOWtests/utils/test_ffmpeg.py55def test_get_none_ffmpeg_version(monkeypatch):
LOWtests/utils/test_ffmpeg.py69def test_get_none_local_ffmpeg(monkeypatch):
LOWtests/utils/test_downloader.py4def test_check_ytmusic_connection_suppresses_empty_search_log(mocker):
LOWtests/utils/test_deno.py33def test_is_not_deno_installed(monkeypatch):
LOWtests/utils/test_deno.py84def test_get_local_deno_yt_dlp_options(monkeypatch, tmp_path):
LOWtests/utils/test_deno.py104def test_get_local_deno_yt_dlp_options_ignores_non_executable(monkeypatch, tmp_path):
LOWtests/utils/test_deno.py118def test_get_local_deno_yt_dlp_options_ignores_missing_local(monkeypatch):
LOWtests/utils/test_deno.py128def test_user_js_runtime_overrides_local_deno(monkeypatch, tmp_path):
LOWtests/utils/test_deno.py147def test_audio_provider_uses_local_deno_yt_dlp_options(monkeypatch, tmp_path):
LOWtests/utils/test_deno.py173def test_piped_uses_local_deno_yt_dlp_options(monkeypatch, tmp_path):
LOWtests/utils/test_deno.py239def test_download_deno_unsupported_platform(monkeypatch):
LOWtests/utils/test_deno.py251def test_download_deno_invalid_archive(monkeypatch, tmp_path):
LOWtests/utils/test_spotify.py45def test_init_uses_free_client_by_default(monkeypatch):
LOWtests/utils/test_spotify.py94def test_init_uses_official_client_when_requested(monkeypatch):
LOWtests/utils/test_spotify.py144def test_init_uses_official_client_for_official_api_only_options(monkeypatch, caplog):
LOWtests/utils/test_arguments.py11def test_parse_use_official_api(monkeypatch):
LOWspotdl/web/routes.py152async def handle_get_client_downloads(datastar_signals: ReadSignals):
LOWspotdl/web/routes.py182async def handle_get_client_settings(datastar_signals: ReadSignals):
LOWspotdl/web/routes.py206async def handle_post_client_settings(datastar_signals: ReadSignals):
LOWspotdl/web/routes.py280async def handle_post_client_download(datastar_signals: ReadSignals):
LOWspotdl/web/routes.py347async def handle_get_client_component_settings(datastar_signals: ReadSignals):
LOWspotdl/web/routes.py387async def handle_client_component_search_input_rotating_placeholder():
LOWspotdl/utils/search.py463def get_user_followed_artists() -> List[Artist]:
LOWspotdl/utils/search.py573def get_song_from_file_metadata(file: Path, id3_separator: str = "/") -> Optional[Song]:
LOWspotdl/utils/deno.py120def get_local_deno_yt_dlp_options() -> Dict[str, Dict[str, Dict[str, str]]]:
LOWspotdl/utils/spotify.py152def _init_official_spotify_client(**kwargs) -> _OfficialSpotifyClient:
LOWspotdl/utils/spotify.py160def _init_free_spotify_client(**kwargs) -> Any:
LOWspotdl/download/progress_handler.py444 def notify_conversion_complete(self, status="Embedding metadata") -> None:
Self-Referential Comments14 hits · 42 pts
SeverityFileLineSnippet
MEDIUMspotdl/web/routes.py92 # Create a new client if not found
MEDIUMspotdl/utils/logging.py187 # Create a rich handler
MEDIUMspotdl/utils/config.py62 # Define the new, correct XDG config path (~/.config/spotdl)
MEDIUMspotdl/utils/config.py65 # Define the old path (~/.spotdl) for backward compatibility
MEDIUMspotdl/utils/metadata.py299 # Create the image object for the file type
MEDIUMspotdl/utils/m3u.py145 # Create a single m3u file for specified song list name
MEDIUMspotdl/download/downloader.py473 # Create the output file path
MEDIUMspotdl/download/downloader.py490 # Create the temp folder path
MEDIUMspotdl/download/downloader.py650 # Create the output directory if it doesn't exist
MEDIUMspotdl/console/save.py88 # The following function calls blocking code, which would block whole event loop.
MEDIUMspotdl/console/web.py58 # Create the event loop
MEDIUMspotdl/console/url.py58 # The following function calls blocking code, which would block whole event loop.
MEDIUMspotdl/console/meta.py36 # Create a list of all songs from all paths in query
MEDIUMspotdl/console/meta.py152 # The following function calls blocking code, which would block whole event loop.
Redundant / Tautological Comments25 hits · 38 pts
SeverityFileLineSnippet
LOWspotdl/types/playlist.py85 # Add tracks to the list
LOWspotdl/providers/audio/sliderkz.py60 # Check if the response is valid
LOWspotdl/providers/audio/base.py254 # Check if any of the search results is in the
LOWspotdl/utils/formatter.py351 # Check if the file name length is greater than the limit
LOWspotdl/utils/web.py128 # Add the connection to the list of connections
LOWspotdl/utils/metadata.py357 # Check if the lyrics are in lrc format
LOWspotdl/utils/metadata.py613 # Check if the lyrics are in lrc format
LOWspotdl/utils/downloader.py19 # Check if we are getting results from YouTube Music
LOWspotdl/utils/ffmpeg.py115 # Check if ffmpeg is installed
LOWspotdl/utils/ffmpeg.py139 # Check if ffmpeg is installed
LOWspotdl/utils/ffmpeg.py320 # Check if bitrate is an integer
LOWspotdl/utils/matching.py489 # # Check if the main artist is simlar
LOWspotdl/utils/matching.py494 # Check if other song artists are in the result name
LOWspotdl/utils/matching.py735 # Check if result contains forbidden words
LOWspotdl/utils/m3u.py110 # Check if the file name ends with .m3u or .m3u8
LOWspotdl/utils/github.py165 # Check if the given url is a url to a GitHub repo. If it is, tell the
LOWspotdl/download/downloader.py441 # Check if song has name/artist and url/song_id
LOWspotdl/download/downloader.py493 # Check if there is an already existing song file, with the same spotify URL in its
LOWspotdl/console/entry_point.py64 # Check if sys.argv contains an action
LOWspotdl/console/entry_point.py91 # Check if ffmpeg is installed
LOWspotdl/console/entry_point.py98 # Check if we might be blocked by YouTube Music without stopping downloads.
LOWspotdl/console/entry_point.py123 # Check if save file is present and if it's valid
LOWspotdl/console/entry_point.py130 # Check if the user is logged in
LOWspotdl/console/meta.py58 # Check if song has metadata
LOWspotdl/console/meta.py122 # Check if the song has lyric
Unused Imports29 hits · 29 pts
SeverityFileLineSnippet
LOWtests/test_main.py3
LOWtests/types/test_song.py3
LOWtests/utils/test_logging.py3
LOWtests/utils/test_archive.py1
LOWtests/utils/test_formatter.py3
LOWtests/utils/test_config.py7
LOWtests/utils/test_m3u.py1
LOWtests/utils/test_ffmpeg.py12
LOWtests/utils/test_deno.py10
LOWspotdl/__init__.py12
LOWspotdl/__init__.py13
LOWspotdl/__main__.py5
LOWspotdl/web/utils.py7
LOWspotdl/providers/lyrics/__init__.py5
LOWspotdl/providers/lyrics/__init__.py6
LOWspotdl/providers/lyrics/__init__.py7
LOWspotdl/providers/lyrics/__init__.py8
LOWspotdl/providers/lyrics/__init__.py9
LOWspotdl/providers/audio/__init__.py5
LOWspotdl/providers/audio/__init__.py6
LOWspotdl/providers/audio/__init__.py6
LOWspotdl/providers/audio/__init__.py6
LOWspotdl/providers/audio/__init__.py6
LOWspotdl/providers/audio/__init__.py12
LOWspotdl/providers/audio/__init__.py13
LOWspotdl/providers/audio/__init__.py14
LOWspotdl/providers/audio/__init__.py15
LOWspotdl/utils/logging.py9
LOWspotdl/console/__init__.py5
Excessive Try-Catch Wrapping22 hits · 22 pts
SeverityFileLineSnippet
LOWtests/conftest.py61 except Exception:
LOWspotdl/__init__.py142 except Exception as exc:
LOWspotdl/web/api.py203 except Exception as exception:
LOWspotdl/web/routes.py338 except Exception as exception:
LOWspotdl/providers/lyrics/base.py82 except Exception as exc:
LOWspotdl/providers/lyrics/base.py120 except Exception as exc:
LOWspotdl/providers/audio/bandcamp.py188 except Exception as exc:
LOWspotdl/providers/audio/sliderkz.py66 except Exception as exc:
LOWspotdl/providers/audio/base.py398 except Exception as exception:
LOWspotdl/providers/audio/piped.py203 except Exception as exception:
LOWspotdl/utils/metadata.py195 except Exception as exc:
LOWspotdl/utils/metadata.py296 except Exception:
LOWspotdl/utils/metadata.py609 except Exception:
LOWspotdl/utils/search.py113 except Exception as exc:
LOWspotdl/utils/lrc.py35 except Exception:
LOWspotdl/download/downloader.py468 except Exception as e:
LOWspotdl/download/downloader.py580 except Exception as exc:
LOWspotdl/download/downloader.py837 except Exception as exception:
LOWspotdl/console/save.py64 except Exception as exception:
LOWspotdl/console/save.py81 except Exception as exception:
LOWspotdl/console/entry_point.py164 except Exception as exc:
LOWspotdl/console/url.py51 except Exception as exception:
Deep Nesting11 hits · 11 pts
SeverityFileLineSnippet
LOWspotdl/providers/audio/base.py154
LOWspotdl/utils/metadata.py277
LOWspotdl/utils/metadata.py384
LOWspotdl/utils/ffmpeg.py251
LOWspotdl/utils/m3u.py21
LOWspotdl/utils/search.py119
LOWspotdl/download/downloader.py98
LOWspotdl/download/downloader.py425
LOWspotdl/console/sync.py21
LOWspotdl/console/meta.py22
LOWspotdl/console/meta.py54
Over-Commented Block7 hits · 7 pts
SeverityFileLineSnippet
LOWtests/test_matching.py261 ),
LOWtests/types/test_song.py121# assert song.album_name == "Ropes"
LOWtests/providers/lyrics/test_azlyrics.py1# import pytest
LOWtests/providers/lyrics/test_musixmatch.py1# import pytest
LOWspotdl/web/api.py41router = APIRouter()
LOWspotdl/web/api.py61# if (
LOWspotdl/providers/lyrics/azlyrics.py161 js_code = None
Cross-Language Confusion1 hit · 2 pts
SeverityFileLineSnippet
HIGHtests/types/test_song.py163 "download_url": null,