Repository: Cog-Creators/Red-DiscordBot

Issue:
playlist list causing UnboundLocalError
### What Red version are you using?

3.4.14

### Cog name

Audio

### Command name

playlist list

### What did you expect to happen?

I first created an empty playlist, and then called `playlist list`, where I expected Red to show me the empty playlist.

### What actually happened?

Red confirmed that it created the empty playlist, but reported that no playlists were found.

### How can we reproduce this error?

1. `[p] playlist create playlistName`
2. `[p] playlist list`


### Anything else?

I found an error in my log files, an `UnboundLocalError` as referenced in the title.
![image](https://user-images.githubusercontent.com/92138376/136501198-5cb5d5c2-140c-4931-b954-ff18af7052ec.png)
Additionally, here is the output of `[p] debuginfo`.
<img width="1112" alt="image" src="https://user-images.githubusercontent.com/92138376/136501321-a604d42d-e837-4bab-8bcc-4c89ba5b7cb5.png">



Discussion:
Switching to python 3.8.12 fixed the `playlist list` issue
This UnboundLocalError appears to happen as this exception is caught and logged, execution continues without defining `row_result`.
https://github.com/Cog-Creators/Red-DiscordBot/blob/334cd4fa2a2d89a0df87d8fa72714edb665db2a3/redbot/cogs/audio/apis/playlist_wrapper.py#L191-L197
Note: The same UnboundLocalError will be thrown whenever ANY of the `row_result = future.result()` lines throw an error, as all 4 are handled the same way in that file.
EDIT: looking again, L108 and L192 are as described, but L140 and L155 are handled fine with a `return`.

@OlorinReborn, I would expect you to see another exception above this one which contains the text `"Failed to completed playlist fetch from database"`. That is what is actually giving you this issue. If you can easily get that traceback as well, that information would also be helpful.



Resolving patch:
diff --git a/redbot/cogs/audio/apis/playlist_wrapper.py b/redbot/cogs/audio/apis/playlist_wrapper.py
--- a/redbot/cogs/audio/apis/playlist_wrapper.py
+++ b/redbot/cogs/audio/apis/playlist_wrapper.py
@@ -84,7 +84,9 @@ def get_scope_type(scope: str) -> int:
             table = 2
         return table
 
-    async def fetch(self, scope: str, playlist_id: int, scope_id: int) -> PlaylistFetchResult:
+    async def fetch(
+        self, scope: str, playlist_id: int, scope_id: int
+    ) -> Optional[PlaylistFetchResult]:
         """Fetch a single playlist."""
         scope_type = self.get_scope_type(scope)
 
@@ -107,7 +109,8 @@ async def fetch(self, scope: str, playlist_id: int, scope_id: int) -> PlaylistFe
                 try:
                     row_result = future.result()
                 except Exception as exc:
-                    debug_exc_log(log, exc, "Failed to completed playlist fetch from database")
+                    debug_exc_log(log, exc, "Failed to complete playlist fetch from database")
+                    return None
             row = row_result.fetchone()
             if row:
                 row = PlaylistFetchResult(*row)
@@ -139,7 +142,7 @@ async def fetch_all(
                     try:
                         row_result = future.result()
                     except Exception as exc:
-                        debug_exc_log(log, exc, "Failed to completed playlist fetch from database")
+                        debug_exc_log(log, exc, "Failed to complete playlist fetch from database")
                         return []
             else:
                 for future in concurrent.futures.as_completed(
@@ -154,7 +157,7 @@ async def fetch_all(
                     try:
                         row_result = future.result()
                     except Exception as exc:
-                        debug_exc_log(log, exc, "Failed to completed playlist fetch from database")
+                        debug_exc_log(log, exc, "Failed to complete playlist fetch from database")
                         return []
         async for row in AsyncIter(row_result):
             output.append(PlaylistFetchResult(*row))
@@ -191,7 +194,8 @@ async def fetch_all_converter(
                 try:
                     row_result = future.result()
                 except Exception as exc:
-                    debug_exc_log(log, exc, "Failed to completed fetch from database")
+                    debug_exc_log(log, exc, "Failed to complete fetch from database")
+                    return []
 
             async for row in AsyncIter(row_result):
                 output.append(PlaylistFetchResult(*row))


Test patch: