Skip to content

Commit 79c87e5

Browse files
authored
Add fetchart typing v2 (#5716)
Adds typings to fetchart; a revised and modernized version of #5213. The former pull request became stale because I did more refactoring there, in order to express properties of the `Candidate` (whether or not it is validated) via the type system (motivated by the type state pattern which is more common in Rust. The result was a little contentious, since it became a little unclear what the purpose of the `Candidate` class should even be at that point. I think this was a case of combining too many things into a single PR. Thus, this version does not perform any refactoring of that extent. It does sprinkle in a few `assert`s to make thinks clear for the type checker.
2 parents f6f5518 + 728076e commit 79c87e5

File tree

6 files changed

+448
-211
lines changed

6 files changed

+448
-211
lines changed

.github/workflows/ci.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
if: matrix.platform == 'ubuntu-latest'
3434
run: |
3535
sudo apt update
36-
sudo apt install ffmpeg gobject-introspection libcairo2-dev libgirepository-2.0-dev pandoc
36+
sudo apt install ffmpeg gobject-introspection libcairo2-dev libgirepository-2.0-dev pandoc imagemagick
3737
3838
- name: Get changed lyrics files
3939
id: lyrics-update
@@ -60,7 +60,7 @@ jobs:
6060
env:
6161
LYRICS_UPDATED: ${{ steps.lyrics-update.outputs.any_changed }}
6262
run: |
63-
poetry install --extras=autobpm --extras=lyrics --extras=docs --extras=replaygain --extras=reflink
63+
poetry install --extras=autobpm --extras=lyrics --extras=docs --extras=replaygain --extras=reflink --extras=fetchart
6464
poe docs
6565
poe test-with-coverage
6666

beets/test/helper.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -886,20 +886,43 @@ class FetchImageHelper:
886886
def run(self, *args, **kwargs):
887887
super().run(*args, **kwargs)
888888

889-
IMAGEHEADER = {
889+
IMAGEHEADER: dict[str, bytes] = {
890890
"image/jpeg": b"\xff\xd8\xff" + b"\x00" * 3 + b"JFIF",
891891
"image/png": b"\211PNG\r\n\032\n",
892+
"image/gif": b"GIF89a",
893+
# dummy type that is definitely not a valid image content type
894+
"image/watercolour": b"watercolour",
895+
"text/html": (
896+
b"<!DOCTYPE html>\n<html>\n<head>\n</head>\n"
897+
b"<body>\n</body>\n</html>"
898+
),
892899
}
893900

894-
def mock_response(self, url, content_type="image/jpeg", file_type=None):
901+
def mock_response(
902+
self,
903+
url: str,
904+
content_type: str = "image/jpeg",
905+
file_type: None | str = None,
906+
) -> None:
907+
# Potentially return a file of a type that differs from the
908+
# server-advertised content type to mimic misbehaving servers.
895909
if file_type is None:
896910
file_type = content_type
911+
912+
try:
913+
# imghdr reads 32 bytes
914+
header = self.IMAGEHEADER[file_type].ljust(32, b"\x00")
915+
except KeyError:
916+
# If we can't return a file that looks like real file of the requested
917+
# type, better fail the test than returning something else, which might
918+
# violate assumption made when writing a test.
919+
raise AssertionError(f"Mocking {file_type} responses not supported")
920+
897921
responses.add(
898922
responses.GET,
899923
url,
900924
content_type=content_type,
901-
# imghdr reads 32 bytes
902-
body=self.IMAGEHEADER.get(file_type, b"").ljust(32, b"\x00"),
925+
body=header,
903926
)
904927

905928

0 commit comments

Comments
 (0)