Add RET505 mypy rule (#2962)
authorOzGav <gavnosp@hotmail.com>
Tue, 20 Jan 2026 15:34:46 +0000 (00:34 +0900)
committerGitHub <noreply@github.com>
Tue, 20 Jan 2026 15:34:46 +0000 (16:34 +0100)
34 files changed:
music_assistant/controllers/config.py
music_assistant/controllers/metadata.py
music_assistant/controllers/music.py
music_assistant/controllers/players/player_controller.py
music_assistant/controllers/players/sync_groups.py
music_assistant/controllers/streams/smart_fades/fades.py
music_assistant/controllers/streams/smart_fades/filters.py
music_assistant/controllers/webserver/helpers/auth_providers.py
music_assistant/helpers/audio.py
music_assistant/helpers/uri.py
music_assistant/models/player.py
music_assistant/providers/audiobookshelf/__init__.py
music_assistant/providers/bbc_sounds/__init__.py
music_assistant/providers/bbc_sounds/adaptor.py
music_assistant/providers/deezer/gw_client.py
music_assistant/providers/filesystem_smb/__init__.py
music_assistant/providers/internet_archive/streaming.py
music_assistant/providers/lrclib/__init__.py
music_assistant/providers/musiccast/provider.py
music_assistant/providers/nicovideo/converters/track.py
music_assistant/providers/opensubsonic/sonic_provider.py
music_assistant/providers/phishin/provider.py
music_assistant/providers/plex/__init__.py
music_assistant/providers/plex/helpers.py
music_assistant/providers/podcast_index/provider.py
music_assistant/providers/snapcast/provider.py
music_assistant/providers/sonos/player.py
music_assistant/providers/soundcloud/__init__.py
music_assistant/providers/spotify/provider.py
music_assistant/providers/subsonic_scrobble/__init__.py
music_assistant/providers/tidal/tidal_page_parser.py
pyproject.toml
tests/providers/nicovideo/fixtures/fixture_loader.py
tests/providers/nicovideo/helpers.py

index 4bc73ffa599795f41701dd6363ce190769a7de64..7a06fe7afeb952ced9ba68f9478cd953c8611d3a 100644 (file)
@@ -750,55 +750,54 @@ class ConfigController:
         """
         if raw_conf := self.get(f"{CONF_PLAYER_DSP}/{player_id}"):
             return DSPConfig.from_dict(raw_conf)
-        else:
-            # return default DSP config
-            dsp_config = DSPConfig()
+        # return default DSP config
+        dsp_config = DSPConfig()
 
-            deprecated_eq_bass = self.mass.config.get_raw_player_config_value(
-                player_id, CONF_DEPRECATED_EQ_BASS, 0
-            )
-            deprecated_eq_mid = self.mass.config.get_raw_player_config_value(
-                player_id, CONF_DEPRECATED_EQ_MID, 0
-            )
-            deprecated_eq_treble = self.mass.config.get_raw_player_config_value(
-                player_id, CONF_DEPRECATED_EQ_TREBLE, 0
-            )
-            if deprecated_eq_bass != 0 or deprecated_eq_mid != 0 or deprecated_eq_treble != 0:
-                # the user previously used the now deprecated EQ settings:
-                # add a tone control filter with the old values, reset the deprecated values and
-                # save this as the new DSP config
-                # TODO: remove this in a future release
-                dsp_config.enabled = True
-                dsp_config.filters.append(
-                    ToneControlFilter(
-                        enabled=True,
-                        bass_level=float(deprecated_eq_bass)
-                        if isinstance(deprecated_eq_bass, (int, float, str))
-                        else 0.0,
-                        mid_level=float(deprecated_eq_mid)
-                        if isinstance(deprecated_eq_mid, (int, float, str))
-                        else 0.0,
-                        treble_level=float(deprecated_eq_treble)
-                        if isinstance(deprecated_eq_treble, (int, float, str))
-                        else 0.0,
-                    )
+        deprecated_eq_bass = self.mass.config.get_raw_player_config_value(
+            player_id, CONF_DEPRECATED_EQ_BASS, 0
+        )
+        deprecated_eq_mid = self.mass.config.get_raw_player_config_value(
+            player_id, CONF_DEPRECATED_EQ_MID, 0
+        )
+        deprecated_eq_treble = self.mass.config.get_raw_player_config_value(
+            player_id, CONF_DEPRECATED_EQ_TREBLE, 0
+        )
+        if deprecated_eq_bass != 0 or deprecated_eq_mid != 0 or deprecated_eq_treble != 0:
+            # the user previously used the now deprecated EQ settings:
+            # add a tone control filter with the old values, reset the deprecated values and
+            # save this as the new DSP config
+            # TODO: remove this in a future release
+            dsp_config.enabled = True
+            dsp_config.filters.append(
+                ToneControlFilter(
+                    enabled=True,
+                    bass_level=float(deprecated_eq_bass)
+                    if isinstance(deprecated_eq_bass, (int, float, str))
+                    else 0.0,
+                    mid_level=float(deprecated_eq_mid)
+                    if isinstance(deprecated_eq_mid, (int, float, str))
+                    else 0.0,
+                    treble_level=float(deprecated_eq_treble)
+                    if isinstance(deprecated_eq_treble, (int, float, str))
+                    else 0.0,
                 )
+            )
 
-                deprecated_eq_keys = [
-                    CONF_DEPRECATED_EQ_BASS,
-                    CONF_DEPRECATED_EQ_MID,
-                    CONF_DEPRECATED_EQ_TREBLE,
-                ]
-                for key in deprecated_eq_keys:
-                    if self.mass.config.get_raw_player_config_value(player_id, key, 0) != 0:
-                        self.mass.config.set_raw_player_config_value(player_id, key, 0)
+            deprecated_eq_keys = [
+                CONF_DEPRECATED_EQ_BASS,
+                CONF_DEPRECATED_EQ_MID,
+                CONF_DEPRECATED_EQ_TREBLE,
+            ]
+            for key in deprecated_eq_keys:
+                if self.mass.config.get_raw_player_config_value(player_id, key, 0) != 0:
+                    self.mass.config.set_raw_player_config_value(player_id, key, 0)
 
-                self.set(f"{CONF_PLAYER_DSP}/{player_id}", dsp_config.to_dict())
-            else:
-                # The DSP config does not do anything by default, so we disable it
-                dsp_config.enabled = False
+            self.set(f"{CONF_PLAYER_DSP}/{player_id}", dsp_config.to_dict())
+        else:
+            # The DSP config does not do anything by default, so we disable it
+            dsp_config.enabled = False
 
-            return dsp_config
+        return dsp_config
 
     @api_command("config/players/dsp/save", required_role="admin")
     async def save_dsp_config(self, player_id: str, config: DSPConfig) -> DSPConfig:
index e50b4db84403ad9ef4b058ea33728f509629ab3f..1c513544f2d8193cd48f9e3ccae991afe2f360ca 100644 (file)
@@ -355,7 +355,7 @@ class MetaDataController(CoreController):
             if media_item.image and media_item.image.type == img_type:
                 if media_item.image.remotely_accessible and resolve:
                     return self.get_image_url(media_item.image)
-                elif not media_item.image.remotely_accessible:
+                if not media_item.image.remotely_accessible:
                     return media_item.image.path
 
             # Only retrieve full item if we don't have the image we need
index 46c5172f289850800489d82aed48cc3e4e378a4b..934786b933d334ac8ab5a232abeccecece91c91b 100644 (file)
@@ -306,18 +306,17 @@ class MusicController(CoreController):
                 else:
                     if media_type == MediaType.ARTIST:
                         return SearchResults(artists=[item])
-                    elif media_type == MediaType.ALBUM:
+                    if media_type == MediaType.ALBUM:
                         return SearchResults(albums=[item])
-                    elif media_type == MediaType.TRACK:
+                    if media_type == MediaType.TRACK:
                         return SearchResults(tracks=[item])
-                    elif media_type == MediaType.PLAYLIST:
+                    if media_type == MediaType.PLAYLIST:
                         return SearchResults(playlists=[item])
-                    elif media_type == MediaType.AUDIOBOOK:
+                    if media_type == MediaType.AUDIOBOOK:
                         return SearchResults(audiobooks=[item])
-                    elif media_type == MediaType.PODCAST:
+                    if media_type == MediaType.PODCAST:
                         return SearchResults(podcasts=[item])
-                    else:
-                        return SearchResults()
+                    return SearchResults()
         # handle normal global search by querying all providers
         results_per_provider: list[SearchResults] = []
         # always first search the library
@@ -1418,8 +1417,7 @@ class MusicController(CoreController):
         # Return the higher position to ensure users never lose progress
         if ma_position_ms >= provider_position_ms:
             return ma_fully_played, ma_position_ms
-        else:
-            return provider_fully_played, provider_position_ms
+        return provider_fully_played, provider_position_ms
 
     def get_controller(
         self, media_type: MediaType
index 6df2cc18d18b2e9b0d569c802867d903c0cd239f..36f589b67cb31e9ac3a301cbcc9ca382c8eca644 100644 (file)
@@ -2040,7 +2040,7 @@ class PlayerController(CoreController):
             # nothing to do anymore, player was not previously powered
             # and does not support power control
             return
-        elif prev_synced_to:
+        if prev_synced_to:
             self.logger.debug(
                 "Announcement to player %s - syncing back to %s...",
                 player.display_name,
index 53b324bf547dbacdfe44c6d4e54769715e1c2c2b..7bc1904616c01c28d23276fee8acbe5aa9a17a84 100644 (file)
@@ -125,8 +125,7 @@ class SyncGroupPlayer(GroupPlayer):
         """Return the current playback state of the player."""
         if self.powered:
             return self.sync_leader.playback_state if self.sync_leader else PlaybackState.IDLE
-        else:
-            return PlaybackState.IDLE
+        return PlaybackState.IDLE
 
     @cached_property
     def flow_mode(self) -> bool:
@@ -177,10 +176,9 @@ class SyncGroupPlayer(GroupPlayer):
         """
         if self.is_dynamic and (leader := self.sync_leader):
             return leader.can_group_with
-        elif self.is_dynamic:
+        if self.is_dynamic:
             return {self.provider.instance_id}
-        else:
-            return set()
+        return set()
 
     async def get_config_entries(
         self,
index 03c11ef99f58298ec3374b834e4aea1f32e64d3c..7c9715622e6b9bf51f56b7be297f2c0b4947cb31 100644 (file)
@@ -138,9 +138,8 @@ class SmartFade(ABC):
 
         if raw_crossfade_output:
             return raw_crossfade_output
-        else:
-            stderr_msg = stderr.decode() if stderr else "(no stderr output)"
-            raise RuntimeError(f"Smart crossfade failed. FFmpeg stderr: {stderr_msg}")
+        stderr_msg = stderr.decode() if stderr else "(no stderr output)"
+        raise RuntimeError(f"Smart crossfade failed. FFmpeg stderr: {stderr_msg}")
 
     def __repr__(self) -> str:
         """Return string representation of SmartFade showing the filter chain."""
index 14e810a2ceb035fc9f9bc557d5fd898400ba5e38..7ace84948739bde0a7801fd68203abe15a3b566d 100644 (file)
@@ -131,18 +131,15 @@ class FrequencySweepFilter(Filter):
             # Exponential curve for smoother transitions
             if direction == "up":
                 return f"'pow({norm_t},2)':eval=frame"
-            else:
-                return f"'1-pow({norm_t},2)':eval=frame"
-        elif curve == "logarithmic":
+            return f"'1-pow({norm_t},2)':eval=frame"
+        if curve == "logarithmic":
             # Logarithmic curve for more aggressive initial change
             if direction == "up":
                 return f"'sqrt({norm_t})':eval=frame"
-            else:
-                return f"'1-sqrt({norm_t})':eval=frame"
-        elif direction == "up":
+            return f"'1-sqrt({norm_t})':eval=frame"
+        if direction == "up":
             return f"'{norm_t}':eval=frame"
-        else:
-            return f"'1-{norm_t}':eval=frame"
+        return f"'1-{norm_t}':eval=frame"
 
     def apply(self, input_fadein_label: str, input_fadeout_label: str) -> list[str]:
         """Generate FFmpeg filters for frequency sweep effect."""
index 97c8009a5914e39a22460258c175c3ec8314189c..b488cf1e66d52de2211137f8a6eb6df7e4656721 100644 (file)
@@ -113,8 +113,7 @@ async def get_ha_user_role(
                 if "system-admin" in group_ids:
                     LOGGER.debug("HA user %s is admin, granting ADMIN role", ha_user_id)
                     return UserRole.ADMIN
-                else:
-                    return UserRole.USER
+                return UserRole.USER
         raise RuntimeError(f"HA user ID {ha_user_id} not found in user list")
     except Exception as err:
         msg = f"Failed to check HA admin status: {err}"
index d8879481e9f9de172df06fd3866f2ace5f721974..81bd683cb88058650c71e35289e49c959b7e855e 100644 (file)
@@ -1136,8 +1136,7 @@ def _get_parts_from_position(
             )
             if i + 1 < len(parts):
                 return parts[i + 1 :], 0
-            else:
-                return parts[i:], int(position)  # last part, cannot skip
+            return parts[i:], int(position)  # last part, cannot skip
 
         return parts[i:], int(position)
 
index c0f58726d4f09a26b2d91199bc1654e7132574e0..5165d2d82d49aea1e11e861637ef27c86372b5e8 100644 (file)
@@ -23,8 +23,7 @@ def valid_id(provider: str, item_id: str) -> bool:
     """Validate Provider ID."""
     if provider == "spotify":
         return valid_base62_length22(item_id)
-    else:
-        return True
+    return True
 
 
 async def parse_uri(uri: str, validate_id: bool = False) -> tuple[MediaType, str, str]:
index 3bebe24ae90616c1fa8f58734ad80b996053f936..f9b334acdf8c9f5a28fd24a6f6e86907cda4c84f 100644 (file)
@@ -263,7 +263,7 @@ class Player(ABC):
         ):
             # always ensure the player_id is in the group_members list for players
             return [self.player_id, *self._attr_group_members]
-        elif self._attr_group_members == [self.player_id]:
+        if self._attr_group_members == [self.player_id]:
             return []
         return self._attr_group_members
 
@@ -1425,7 +1425,7 @@ class Player(ABC):
                 elapsed_time=int(active_queue.elapsed_time),
                 elapsed_time_last_updated=active_queue.elapsed_time_last_updated,
             )
-        elif active_queue:
+        if active_queue:
             # queue is active but no current item
             return None
         # return native current media if no group/queue is active
index 0852182c5a8ca923ed85c3593dcb455861b8c694..bbbc3ea243e069fe594f9c034a530c6dddcf6a26 100644 (file)
@@ -555,7 +555,7 @@ for more details.
         """Get stream of item."""
         if media_type == MediaType.PODCAST_EPISODE:
             return await self._get_stream_details_episode(item_id)
-        elif media_type == MediaType.AUDIOBOOK:
+        if media_type == MediaType.AUDIOBOOK:
             abs_audiobook = await self._get_abs_expanded_audiobook(prov_audiobook_id=item_id)
             return await self._get_stream_details_audiobook(abs_audiobook)
         raise MediaNotFoundError("Stream unknown")
@@ -1048,9 +1048,8 @@ for more details.
         if len(sub_path) == 1:
             if lib_key == AbsBrowsePaths.LIBRARIES_PODCAST:
                 return await self._browse_lib_podcasts(library_id=lib_id)
-            else:
-                return self._browse_lib_audiobooks(current_path=path)
-        elif len(sub_path) == 2:
+            return self._browse_lib_audiobooks(current_path=path)
+        if len(sub_path) == 2:
             item_key = sub_path[1]
             match item_key:
                 case AbsBrowsePaths.AUTHORS:
index 1c2b5d12e4646f8112d973b1b23f9317b13d6036..5ff5bc991e00dbe4517b683a6d0170f74fc13a80 100644 (file)
@@ -308,8 +308,7 @@ class BBCSoundsProvider(MusicProvider):
         self.logger.debug(f"Getting stream details for {item_id} ({media_type})")
         if media_type in [MediaType.PODCAST_EPISODE, MediaType.TRACK]:
             return await self._get_playable_stream_details(item_id, media_type)
-        else:
-            return await self._get_station_stream_details(item_id)
+        return await self._get_station_stream_details(item_id)
 
     async def _get_programme_segments(self, vpid: str) -> list[Segment] | None:
         """Get on demand segments from cache or API."""
@@ -465,8 +464,7 @@ class BBCSoundsProvider(MusicProvider):
                 for obj in [await self._render_browse_item(item) for item in category.sub_items]
                 if obj is not None
             ]
-        else:
-            return []
+        return []
 
     async def _get_collection(
         self, pid: str
@@ -480,16 +478,14 @@ class BBCSoundsProvider(MusicProvider):
                 ]
                 if obj
             ]
-        else:
-            return []
+        return []
 
     async def _get_menu(
         self, path_parts: list[str] | None = None
     ) -> Sequence[MediaItemType | ItemMapping | BrowseFolder]:
         if self.client.auth.is_logged_in and await self.client.auth.is_uk_listener:
             return await self._get_full_menu(path_parts=path_parts)
-        else:
-            return await self._get_slim_menu(path_parts=path_parts)
+        return await self._get_slim_menu(path_parts=path_parts)
 
     async def _get_full_menu(
         self, path_parts: list[str] | None = None
@@ -563,8 +559,7 @@ class BBCSoundsProvider(MusicProvider):
             (BrowseFolder | Track | Podcast | PodcastEpisode | RecommendationFolder | Radio),
         ):
             return new_item
-        else:
-            return None
+        return None
 
     async def _get_subpath_menu(
         self, sub_path: str
@@ -626,7 +621,7 @@ class BBCSoundsProvider(MusicProvider):
                     if new_folder:
                         items.append(new_folder)
             return items
-        elif sub_sub_path:
+        if sub_sub_path:
             # Date listings for a station
             date_folders = [
                 BrowseFolder(
@@ -662,25 +657,24 @@ class BBCSoundsProvider(MusicProvider):
                     ]
                 )
             return date_folders
-        else:
-            return [
-                BrowseFolder(
-                    item_id=station.item_id,
-                    provider=self.domain,
-                    name=station.name,
-                    path="/".join([*path_parts, station.item_id]),
-                    image=(
-                        MediaItemImage(
-                            type=ImageType.THUMB,
-                            path=station.metadata.images[0].path,
-                            provider=self.domain,
-                        )
-                        if station.metadata.images
-                        else None
-                    ),
-                )
-                for station in await self._station_list(include_local=show_local)
-            ]
+        return [
+            BrowseFolder(
+                item_id=station.item_id,
+                provider=self.domain,
+                name=station.name,
+                path="/".join([*path_parts, station.item_id]),
+                image=(
+                    MediaItemImage(
+                        type=ImageType.THUMB,
+                        path=station.metadata.images[0].path,
+                        provider=self.domain,
+                    )
+                    if station.metadata.images
+                    else None
+                ),
+            )
+            for station in await self._station_list(include_local=show_local)
+        ]
 
     async def browse(self, path: str) -> Sequence[MediaItemType | ItemMapping | BrowseFolder]:
         """Browse this provider's items.
@@ -702,18 +696,17 @@ class BBCSoundsProvider(MusicProvider):
 
         if sub_path == "":
             return await self._get_menu()
-        elif sub_path == "categories" and sub_sub_path:
+        if sub_path == "categories" and sub_sub_path:
             return await self._get_category(sub_sub_path)
-        elif sub_path == "collections" and sub_sub_path:
+        if sub_path == "collections" and sub_sub_path:
             return await self._get_collection(sub_sub_path)
-        elif sub_path != "stations":
+        if sub_path != "stations":
             return await self._get_subpath_menu(sub_path)
-        elif sub_path == "stations":
+        if sub_path == "stations":
             return await self._get_station_schedule_menu(
                 self.show_local_stations, path_parts, sub_sub_path, sub_sub_sub_path
             )
-        else:
-            return []
+        return []
 
     async def search(
         self, search_query: str, media_types: list[MediaType] | None, limit: int = 5
index 77cef39ad3df466f9c7753c5b594e467dc96d29f..c9ce97d560fbc8c1ee67f99662f387fbace740e0 100644 (file)
@@ -273,9 +273,9 @@ class StationConverter(BaseConverter):
         """Convert the source object to target type."""
         if isinstance(source_obj, Station):
             return self._convert_station(source_obj)
-        elif isinstance(source_obj, LiveStation):
+        if isinstance(source_obj, LiveStation):
             return self._convert_live_station(source_obj)
-        elif isinstance(source_obj, StationSearchResult):
+        if isinstance(source_obj, StationSearchResult):
             return self._convert_station_search_result(source_obj)
         self.logger.error(f"Failed to convert station {type(source_obj)}: {source_obj}")
         raise ConversionError(f"Failed to convert station {type(source_obj)}: {source_obj}")
@@ -348,7 +348,7 @@ class PodcastConverter(BaseConverter):
                 show_title=show.titles["secondary"],
                 date=_to_date(show.start),
             )
-        elif show.titles:
+        if show.titles:
             # TODO: when getting a schedule listing, we have a broadcast time
             # when we fetch the streaming details later we lose that from the new API call
             title = self.SCHEDULE_ITEM_DEFAULT_FORMAT.format(
@@ -461,11 +461,11 @@ class PodcastConverter(BaseConverter):
         """Convert podcast objects."""
         if isinstance(source_obj, (Podcast, RadioSeries)) or self.context.force_type is Podcast:
             return await self._convert_podcast(source_obj)
-        elif isinstance(source_obj, PodcastEpisode):
+        if isinstance(source_obj, PodcastEpisode):
             return await self._convert_podcast_episode(source_obj)
-        elif isinstance(source_obj, RadioShow):
+        if isinstance(source_obj, RadioShow):
             return await self._convert_radio_show(source_obj)
-        elif isinstance(source_obj, RadioClip) or self.context.force_type is Track:
+        if isinstance(source_obj, RadioClip) or self.context.force_type is Track:
             return await self._convert_radio_clip(source_obj)
         return source_obj
 
@@ -555,28 +555,27 @@ class PodcastConverter(BaseConverter):
                 ),
                 provider_mappings={self._create_provider_mapping(show.pid)},
             )
-        else:
-            # Handle as episode
-            podcast = None
-            if hasattr(show, "container") and show.container:
-                podcast = await PodcastConverter(self.context).convert(show.container)
+        # Handle as episode
+        podcast = None
+        if hasattr(show, "container") and show.container:
+            podcast = await PodcastConverter(self.context).convert(show.container)
 
-            if not podcast or not isinstance(podcast, MAPodcast):
-                raise ConversionError(f"No podcast for episode for {show}")
+        if not podcast or not isinstance(podcast, MAPodcast):
+            raise ConversionError(f"No podcast for episode for {show}")
 
-            return MAPodcastEpisode(
-                item_id=show.pid,
-                name=self._format_show_title(show),
-                provider=self.context.provider_domain,
-                duration=duration,
-                resume_position_ms=resume_position,
-                metadata=ImageProvider.create_metadata_with_image(
-                    show.image_url, self.context.provider_domain
-                ),
-                podcast=podcast,
-                provider_mappings={self._create_provider_mapping(show.pid)},
-                position=1,
-            )
+        return MAPodcastEpisode(
+            item_id=show.pid,
+            name=self._format_show_title(show),
+            provider=self.context.provider_domain,
+            duration=duration,
+            resume_position_ms=resume_position,
+            metadata=ImageProvider.create_metadata_with_image(
+                show.image_url, self.context.provider_domain
+            ),
+            podcast=podcast,
+            provider_mappings={self._create_provider_mapping(show.pid)},
+            position=1,
+        )
 
     async def _convert_radio_clip(self, clip: RadioClip) -> Track | MAPodcastEpisode:
         duration = self._get_attr(clip, "duration.value")
@@ -604,17 +603,16 @@ class PodcastConverter(BaseConverter):
                 podcast=podcast,
                 position=0,
             )
-        else:
-            return Track(
-                item_id=clip.pid,
-                name=self._get_attr(clip, "titles.entity_title", "Unknown Track"),
-                provider=self.context.provider_domain,
-                duration=duration,
-                metadata=ImageProvider.create_metadata_with_image(
-                    clip.image_url, self.context.provider_domain, description
-                ),
-                provider_mappings={self._create_provider_mapping(clip.pid)},
-            )
+        return Track(
+            item_id=clip.pid,
+            name=self._get_attr(clip, "titles.entity_title", "Unknown Track"),
+            provider=self.context.provider_domain,
+            duration=duration,
+            metadata=ImageProvider.create_metadata_with_image(
+                clip.image_url, self.context.provider_domain, description
+            ),
+            provider_mappings={self._create_provider_mapping(clip.pid)},
+        )
 
 
 class BrowseConverter(BaseConverter):
@@ -642,11 +640,11 @@ class BrowseConverter(BaseConverter):
         """Convert browsable objects."""
         if isinstance(source_obj, MenuItem) and self.context.force_type is not RecommendationFolder:
             return self._convert_menu_item(source_obj)
-        elif isinstance(source_obj, (Category, Collection)):
+        if isinstance(source_obj, (Category, Collection)):
             return self._convert_category_or_collection(source_obj)
-        elif isinstance(source_obj, Schedule):
+        if isinstance(source_obj, Schedule):
             return self._convert_schedule(source_obj)
-        elif isinstance(source_obj, RecommendedMenuItem):
+        if isinstance(source_obj, RecommendedMenuItem):
             return await self._convert_recommended_item(source_obj)
         self.logger.error(f"Failed to convert browse object {type(source_obj)}: {source_obj}")
         raise ConversionError(f"Browse conversion failed: {source_obj}")
index 8633135341c4352d9759fa9ae3c408419cf0d17e..70eb267ae563439090edcf8d52a0cd26676297f3 100644 (file)
@@ -122,9 +122,8 @@ class GWClient:
                 return await self._gw_api_call(
                     method, use_csrf_token, args, params, http_method, False
                 )
-            else:
-                msg = "Failed to call GW-API"
-                raise DeezerGWError(msg, result_json["error"])
+            msg = "Failed to call GW-API"
+            raise DeezerGWError(msg, result_json["error"])
         return cast("dict[str, Any]", result_json)
 
     async def get_song_data(self, track_id: str) -> dict[str, Any]:
index 783adaf24191c3b3ced179b68da668fa911d192a..77c7c40b778a2c5f98bd793260ef5c3ce4bac571 100644 (file)
@@ -187,7 +187,7 @@ class SMBFileSystemProvider(LocalFileSystemProvider):
         subfolder = str(self.config.get_value(CONF_SUBFOLDER))
         if subfolder:
             return subfolder
-        elif share:
+        if share:
             return share
         return None
 
index 072487ed7a6e3750b7ca6f1fd2953f3da8872f07..d9c09e0967c6e3da069237574a45c90b387bbfa4 100644 (file)
@@ -29,15 +29,13 @@ class InternetArchiveStreaming:
         """Get streamdetails for a track or audiobook."""
         if "#" in item_id:
             return self._get_single_file_stream(item_id, {}, media_type)
-        else:
-            audio_files = await self.provider.client.get_audio_files(item_id)
-            if not audio_files:
-                raise MediaNotFoundError(f"No audio files found for {item_id}")
-
-            if media_type == MediaType.AUDIOBOOK and len(audio_files) > 1:
-                return await self._get_multi_file_audiobook_stream(item_id, audio_files)
-            else:
-                return self._get_single_file_stream(item_id, audio_files[0], media_type)
+        audio_files = await self.provider.client.get_audio_files(item_id)
+        if not audio_files:
+            raise MediaNotFoundError(f"No audio files found for {item_id}")
+
+        if media_type == MediaType.AUDIOBOOK and len(audio_files) > 1:
+            return await self._get_multi_file_audiobook_stream(item_id, audio_files)
+        return self._get_single_file_stream(item_id, audio_files[0], media_type)
 
     async def _get_multi_file_audiobook_stream(
         self, item_id: str, audio_files: list[dict[str, Any]]
index 1c96c8fb4ce7b11fe6548ed26a3e1a29ac276f14..6b08177dbaa25f76fa431107864ae305301ebd71 100644 (file)
@@ -148,15 +148,14 @@ class LrclibProvider(MetadataProvider):
                 self.logger.debug("Found synchronized lyrics for %s by %s", track.name, artist_name)
                 return metadata
 
-            else:
-                self.logger.debug(
-                    "No synchronized lyrics found for %s by %s with album name %s and with a "
-                    "duration within 2 secs of %s",
-                    track.name,
-                    artist_name,
-                    album_name,
-                    duration,
-                )
+            self.logger.debug(
+                "No synchronized lyrics found for %s by %s with album name %s and with a "
+                "duration within 2 secs of %s",
+                track.name,
+                artist_name,
+                album_name,
+                duration,
+            )
 
             plain_lyrics = data.get("plainLyrics")
 
@@ -166,13 +165,12 @@ class LrclibProvider(MetadataProvider):
 
                 self.logger.debug("Found plain lyrics for %s by %s", track.name, artist_name)
                 return metadata
-            else:
-                self.logger.info(
-                    "No lyrics found for %s by %s with album name %s and with a "
-                    "duration within 2 secs of %s",
-                    track.name,
-                    artist_name,
-                    album_name,
-                    duration,
-                )
+            self.logger.info(
+                "No lyrics found for %s by %s with album name %s and with a "
+                "duration within 2 secs of %s",
+                track.name,
+                artist_name,
+                album_name,
+                duration,
+            )
         return None
index a16440cc4a3843f01f959facaecb276f4be3f7a1..45bcc0b7389995c908300853e14fc82ac177af21 100644 (file)
@@ -169,25 +169,24 @@ class MusicCastProvider(PlayerProvider):
         ):
             # nothing to do, device is already connected
             return
-        else:
-            # new or updated player detected
-            physical_device = MusicCastPhysicalDevice(
-                device=MusicCastDevice(
-                    client=self.mass.http_session,
-                    ip=device_ip,
-                    upnp_description=description_url,
-                ),
-                controller=self.mc_controller,
+        # new or updated player detected
+        physical_device = MusicCastPhysicalDevice(
+            device=MusicCastDevice(
+                client=self.mass.http_session,
+                ip=device_ip,
+                upnp_description=description_url,
+            ),
+            controller=self.mc_controller,
+        )
+        self.update_player_locks[device_id] = asyncio.Lock()
+        success = await physical_device.async_init()  # fetch + polling
+        if not success:
+            self.logger.debug(
+                "Had trouble setting up device at %s. Will be retried on next discovery.",
+                device_ip,
             )
-            self.update_player_locks[device_id] = asyncio.Lock()
-            success = await physical_device.async_init()  # fetch + polling
-            if not success:
-                self.logger.debug(
-                    "Had trouble setting up device at %s. Will be retried on next discovery.",
-                    device_ip,
-                )
-                return
-            await self._register_player(physical_device, device_id)
+            return
+        await self._register_player(physical_device, device_id)
 
     async def _register_player(
         self, physical_device: MusicCastPhysicalDevice, device_id: str
index c67acdb1f0bd85d02b824faf9893bcc8d9d4e242..323ac1c7de168ca6e518cf0f02995845836372fe 100644 (file)
@@ -426,5 +426,5 @@ class NicovideoTrackConverter(NicovideoConverterBase):
         # Type-specific availability checks
         if isinstance(video, EssentialVideo):
             return not video.is_payment_required and not video.is_muted
-        else:  # WatchVideo
-            return not video.is_deleted
+        # WatchVideo
+        return not video.is_deleted
index a8a1cc43670890c1f357989fa4a43ecaa06cf9ae..54ec9e7a7f4f77f6442c07c94ad29d463aa7beba 100644 (file)
@@ -388,7 +388,7 @@ class OpenSonicProvider(MusicProvider):
                     )
                 },
             )
-        elif prov_artist_id.startswith(NAVI_VARIOUS_PREFIX):
+        if prov_artist_id.startswith(NAVI_VARIOUS_PREFIX):
             # Special case for handling track artists on various artists album for Navidrome.
             return Artist(
                 item_id=prov_artist_id,
index 73c3423b60fdffdb2c59b474f6ee75d7945f1d07..ca62c87d38799677e1906f89acec848cb7a6c83c 100644 (file)
@@ -496,21 +496,21 @@ class PhishInProvider(MusicProvider):
                 if len(playlists) >= 50:
                     break
             return playlists
-        elif subpath == "years":
+        if subpath == "years":
             return await self._browse_years(path, subsubpath)
-        elif subpath == "recent":
+        if subpath == "recent":
             return await self._browse_recent()
-        elif subpath == "random":
+        if subpath == "random":
             return await self._browse_random()
-        elif subpath == "today":
+        if subpath == "today":
             return await self._browse_today()
-        elif subpath == "venues":
+        if subpath == "venues":
             return await self._browse_venues(path, subsubpath)
-        elif subpath == "tags":
+        if subpath == "tags":
             return await self._browse_tags(path, subsubpath)
-        elif subpath == "top_shows":
+        if subpath == "top_shows":
             return await self._browse_top_shows()
-        elif subpath == "top_tracks":
+        if subpath == "top_tracks":
             return await self._browse_top_tracks()
 
         return []
@@ -780,10 +780,9 @@ class PhishInProvider(MusicProvider):
             tag_slug, content_type = subsubpath.split("/", 1)
             if content_type == "shows":
                 return await self._get_shows_for_tag(tag_slug)
-            elif content_type == "tracks":
+            if content_type == "tracks":
                 return await self._get_tracks_for_tag(tag_slug)
-            else:
-                return []
+            return []
 
     @use_cache(expiration=86400)  # 24 hours - Tag associations could change as new shows are tagged
     async def _get_tracks_for_tag(self, tag_slug: str) -> list[BrowseFolder | Album | Track]:
index 2bb5c57bbcadc082ac16a8688cd55e0a664acfdb..895c795c7b251ec8cb9d21c78afa0015f716e5f6 100644 (file)
@@ -589,11 +589,11 @@ class PlexProvider(MusicProvider):
     async def _parse(self, plex_media: PlexObject) -> MediaItem | None:
         if plex_media.type == "artist":
             return await self._parse_artist(plex_media)
-        elif plex_media.type == "album":
+        if plex_media.type == "album":
             return await self._parse_album(plex_media)
-        elif plex_media.type == "track":
+        if plex_media.type == "track":
             return await self._parse_track(plex_media)
-        elif plex_media.type == "playlist":
+        if plex_media.type == "playlist":
             return await self._parse_playlist(plex_media)
         return None
 
index 665026e1e1b6c9c32396fc1fe0036c82bc1d7ae1..b8cb35aedcfce962a5edb07f847f5037960d5cdd 100644 (file)
@@ -92,7 +92,6 @@ async def discover_local_servers() -> tuple[str, int] | tuple[None, None]:
             local_server_ip = entry.get("from")[0]
             local_server_port = data.get("Port")
             return local_server_ip, local_server_port
-        else:
-            return None, None
+        return None, None
 
     return await asyncio.to_thread(_discover_local_servers)
index d39265b8fa974d355a1b5671c87f103afb8e14af..b2d02a17e2bd8ea84a66a233fc37d302401f13bc 100644 (file)
@@ -127,16 +127,15 @@ class PodcastIndexProvider(MusicProvider):
 
             if subpath == BROWSE_TRENDING:
                 return await self._browse_trending()
-            elif subpath == BROWSE_RECENT:
+            if subpath == BROWSE_RECENT:
                 return await self._browse_recent_episodes()
-            elif subpath == BROWSE_CATEGORIES:
+            if subpath == BROWSE_CATEGORIES:
                 if len(subpath_parts) > 1:
                     # Browse specific category - category name is directly in path
                     category_name = subpath_parts[1]
                     return await self._browse_category_podcasts(category_name)
-                else:
-                    # Browse categories
-                    return await self._browse_categories()
+                # Browse categories
+                return await self._browse_categories()
 
         return []
 
@@ -363,10 +362,9 @@ class PodcastIndexProvider(MusicProvider):
         """Get single MediaItem from provider."""
         if media_type == MediaType.PODCAST:
             return await self.get_podcast(prov_item_id)
-        elif media_type == MediaType.PODCAST_EPISODE:
+        if media_type == MediaType.PODCAST_EPISODE:
             return await self.get_podcast_episode(prov_item_id)
-        else:
-            raise MediaNotFoundError(f"Media type {media_type} not supported by this provider")
+        raise MediaNotFoundError(f"Media type {media_type} not supported by this provider")
 
     async def _fetch_podcasts(
         self, endpoint: str, params: dict[str, Any] | None = None
index 94c197fc7bcfd1b84e58cb102b81e56cdffefe3a..7d465d8c49d1189c63f0fc537b9b56aa8ceae703 100644 (file)
@@ -265,8 +265,7 @@ class SnapCastProvider(PlayerProvider):
             new_id = "ma_" + str(re.sub(r"\W+", "", snap_client_id))
             self._ids_map[new_id] = snap_client_id
             return new_id
-        else:
-            return self._get_ma_id(snap_client_id)
+        return self._get_ma_id(snap_client_id)
 
     def _handle_player_init(self, snap_client: Snapclient) -> SnapCastPlayer:
         """Process Snapcast add to Player controller."""
index c3b7d55208a661beee90545ac60180de6458cd80..26115367eb376ab6a8edbe31afda70327bd8f628 100644 (file)
@@ -617,8 +617,7 @@ class SonosPlayer(Player):
                 self._attr_current_media = airplay_player.current_media
                 # return early as we dont need further info
                 return
-            else:
-                self._attr_active_source = SOURCE_AIRPLAY
+            self._attr_active_source = SOURCE_AIRPLAY
         elif (
             container_type == ContainerType.STATION
             and active_service != MusicService.MUSIC_ASSISTANT
index 5cb8fd044548b591963be327e8baa95c1fce4068..6df273a2d103c6a66a331cfa14e2179eb5f71c76 100644 (file)
@@ -305,10 +305,9 @@ class SoundcloudMusicProvider(MusicProvider):
             # Handle system playlists
             result = await self._soundcloud.get_system_playlist_details(prov_playlist_id)
             return cast("dict[str, Any]", result)
-        else:
-            # Handle regular playlists
-            result = await self._soundcloud.get_playlist_details(prov_playlist_id)
-            return cast("dict[str, Any]", result)
+        # Handle regular playlists
+        result = await self._soundcloud.get_playlist_details(prov_playlist_id)
+        return cast("dict[str, Any]", result)
 
     @use_cache(3600 * 3)  # Cache for 3 hours
     async def get_playlist_tracks(self, prov_playlist_id: str, page: int = 0) -> list[Track]:
index b6ec37a735cadeb418a5cb0ba9cbd71980ab4886..f74cc79f09bd272749e061f8353c00d83d1aaceb 100644 (file)
@@ -481,7 +481,7 @@ class SpotifyProvider(MusicProvider):
             position_ms = resume_point.get("resume_position_ms", 0)
             return fully_played, position_ms
 
-        elif media_type == MediaType.AUDIOBOOK:
+        if media_type == MediaType.AUDIOBOOK:
             if not self.audiobooks_supported:
                 raise NotImplementedError("Audiobook support is disabled")
             if not self.audiobook_progress_sync_enabled:
index 56eb31cd0c1b201667c00f21ed13d726bc05b9e5..26e980d2b10b59236018d38ed01eebe193be0024 100644 (file)
@@ -109,7 +109,7 @@ class SubsonicScrobbleEventHandler(ScrobblerHelper):
                     return prov, ret_id
             # no subsonic mapping has been found in library item, ignore...
             return None, item_id
-        elif provider_instance_id_or_domain.startswith("opensubsonic"):
+        if provider_instance_id_or_domain.startswith("opensubsonic"):
             # found a subsonic mapping, proceed...
             prov = self.mass.get_provider(provider_instance_id_or_domain)
             assert isinstance(prov, OpenSonicProvider)
index a7e664aa0e1bb0bcb84ac9555c8cb34582fdb588..d2abf987435e95706cfc61297d3f95ea36a85619 100644 (file)
@@ -345,39 +345,38 @@ class TidalPageParser:
                 )
                 type_counts[MediaType.PLAYLIST] += 1
                 return media_item
-            elif item_type == "PLAYLIST":
+            if item_type == "PLAYLIST":
                 media_item = parse_playlist(self.provider, item)
                 type_counts[MediaType.PLAYLIST] += 1
                 return media_item
-            elif item_type == "ALBUM":
+            if item_type == "ALBUM":
                 media_item = parse_album(self.provider, item)
                 type_counts[MediaType.ALBUM] += 1
                 return media_item
-            elif item_type == "TRACK":
+            if item_type == "TRACK":
                 media_item = parse_track(self.provider, item)
                 type_counts[MediaType.TRACK] += 1
                 return media_item
-            elif item_type == "ARTIST":
+            if item_type == "ARTIST":
                 media_item = parse_artist(self.provider, item)
                 type_counts[MediaType.ARTIST] += 1
                 return media_item
-            else:
-                # Last resort - try to infer from structure for unlabeled items
-                if "uuid" in item:
-                    media_item = parse_playlist(self.provider, item)
-                    type_counts[MediaType.PLAYLIST] += 1
-                    return media_item
-                elif "id" in item and "title" in item and "duration" in item:
-                    media_item = parse_track(self.provider, item)
-                    type_counts[MediaType.TRACK] += 1
-                    return media_item
-                elif "id" in item and "title" in item and "numberOfTracks" in item:
-                    media_item = parse_album(self.provider, item)
-                    type_counts[MediaType.ALBUM] += 1
-                    return media_item
+            # Last resort - try to infer from structure for unlabeled items
+            if "uuid" in item:
+                media_item = parse_playlist(self.provider, item)
+                type_counts[MediaType.PLAYLIST] += 1
+                return media_item
+            if "id" in item and "title" in item and "duration" in item:
+                media_item = parse_track(self.provider, item)
+                type_counts[MediaType.TRACK] += 1
+                return media_item
+            if "id" in item and "title" in item and "numberOfTracks" in item:
+                media_item = parse_album(self.provider, item)
+                type_counts[MediaType.ALBUM] += 1
+                return media_item
 
-                self.logger.warning("Unknown item type, could not parse: %s", item)
-                return None
+            self.logger.warning("Unknown item type, could not parse: %s", item)
+            return None
 
         except (KeyError, ValueError, TypeError) as err:
             self.logger.debug("Error parsing %s item: %s", item_type, err)
index 09e866c09d24348d535d557f45c6f35d0e743bef..d55c64af177dfa0bc301a1f5c34fc1c71e8c8697 100644 (file)
@@ -232,7 +232,6 @@ ignore = [
   "ARG002",
   "S311",
   "TRY301",
-  "RET505",
   "PLR0912",
   "B904",
   "TRY401",
index 52f1abb5fc17b96d204f6e4637f69ea8d1362444..78e0e2e058f3d8907df19cdc1da39d7033404d35 100644 (file)
@@ -32,9 +32,8 @@ class FixtureLoader:
         try:
             if isinstance(data, list):
                 return [fixture_type.model_validate(item) for item in data]
-            else:
-                # Single object case
-                return fixture_type.model_validate(data)
+            # Single object case
+            return fixture_type.model_validate(data)
         except Exception as e:
             pytest.fail(f"Failed to validate fixture {relative_path}: {e}")
 
index 5f8620e4ae09b8073090c92b17744fdbad8235b1..602910246527dd65a9dfc97e7864bffc68f733ba 100644 (file)
@@ -41,7 +41,7 @@ def sort_dict_keys_and_lists(obj: JsonValue) -> JsonValue:
     if isinstance(obj, dict):
         # Sort dictionary keys and recursively process values
         return {key: sort_dict_keys_and_lists(obj[key]) for key in sorted(obj.keys())}
-    elif isinstance(obj, list):
+    if isinstance(obj, list):
         # Recursively process list items first
         sorted_items = [sort_dict_keys_and_lists(item) for item in obj]
         try: