Skip to main content

Allow passing both width and height as part of ThumbnailConfig

ID
8476cf4
date
2025-12-09 21:27:33+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
76e9021
message
Allow passing both `width` and `height` as part of `ThumbnailConfig`
changed files
3 files, 12 additions, 15 deletions

Changed files

CHANGELOG.md (2134) → CHANGELOG.md (2270)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 13bab8d..4a117e0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # CHANGELOG
 
+## v19 - 2025-12-09
+
+Allow passing both `width` and `height` as part of `ThumbnailConfig`, to constrain a thumbnail to a bounding box.
+
 ## v18 - 2025-12-08
 
 Expose `get_tint_colour()` as a public function from `chives.media`.

src/chives/__init__.py (391) → src/chives/__init__.py (391)

diff --git a/src/chives/__init__.py b/src/chives/__init__.py
index 70a31b1..10699f4 100644
--- a/src/chives/__init__.py
+++ b/src/chives/__init__.py
@@ -11,4 +11,4 @@ I share across multiple sites.
 
 """
 
-__version__ = "18"
+__version__ = "19"

src/chives/media.py (10665) → src/chives/media.py (10314)

diff --git a/src/chives/media.py b/src/chives/media.py
index 71551ad..46139dc 100644
--- a/src/chives/media.py
+++ b/src/chives/media.py
@@ -18,7 +18,7 @@ from fractions import Fraction
 import json
 from pathlib import Path
 import subprocess
-from typing import cast, Literal, NotRequired, TypedDict, TYPE_CHECKING
+from typing import Literal, NotRequired, TypedDict, TYPE_CHECKING
 
 if TYPE_CHECKING:
     import PIL
@@ -166,13 +166,10 @@ def get_media_paths(e: MediaEntity) -> set[Path]:
     return {Path(p) for p in result}
 
 
-_ThumbnailByWidthConfig = TypedDict(
-    "_ThumbnailByWidthConfig", {"out_dir": str | Path, "width": int}
-)
-_ThumbnailByHeightConfig = TypedDict(
-    "_ThumbnailByHeightConfig", {"out_dir": str | Path, "height": int}
-)
-ThumbnailConfig = _ThumbnailByWidthConfig | _ThumbnailByHeightConfig
+class ThumbnailConfig(TypedDict):
+    out_dir: Path | str
+    width: NotRequired[int]
+    height: NotRequired[int]
 
 
 def create_image_entity(
@@ -327,15 +324,11 @@ def _create_thumbnail(path: str | Path, thumbnail_config: ThumbnailConfig) -> st
     cmd = ["create_thumbnail", str(path), "--out-dir", thumbnail_config["out_dir"]]
 
     if "width" in thumbnail_config:
-        config_w = cast(_ThumbnailByWidthConfig, thumbnail_config)
-        cmd.extend(["--width", str(config_w["width"])])
+        cmd.extend(["--width", str(thumbnail_config["width"])])
 
-    elif "height" in thumbnail_config:
+    if "height" in thumbnail_config:
         cmd.extend(["--height", str(thumbnail_config["height"])])
 
-    else:  # pragma: no cover
-        raise TypeError(f"Unrecognised thumbnail config: {thumbnail_config!r}")
-
     return subprocess.check_output(cmd, text=True)