import pytest from PIL import Image from pigway_frame_flow.providers.photo_sources import PhotoSourceInput @pytest.fixture def oriented(service, settings): settings.photo_root = settings.data_dir.parent / "photos" root = settings.photo_root / "20240101 Day" root.mkdir(parents=True) for name, size, rotation in [ ("wide.jpg", (200, 100), 1), ("tall.jpg", (100, 200), 1), ("rotated.jpg", (200, 100), 6), ("square.jpg", (100, 100), 1), ]: exif = Image.Exif() exif[274] = rotation Image.new("RGB", size).save(root / name, exif=exif) return service.photo_sources @pytest.mark.parametrize( "direction,names", [ ("landscape", {"wide.jpg"}), ("portrait", {"tall.jpg", "rotated.jpg"}), ("auto", {"tall.jpg", "rotated.jpg"}), (None, {"wide.jpg", "tall.jpg", "rotated.jpg", "square.jpg"}), ], ) def test_orientation_catalog_and_exif(oriented, direction, names): oriented.save( "family", PhotoSourceInput( name="Family", kind="local", location=".", orientation=direction, organized_only=True, ), ) rows = oriented.catalog("family") assert {r["name"] for r in rows} == names if direction: assert oriented.db.one("SELECT COUNT(*) AS n FROM photo_dimensions")["n"] == 4 if direction != "landscape": rotated = next(r for r in rows if r["name"] == "rotated.jpg") assert (rotated["width"], rotated["height"]) == (100, 200) def test_cached_dimensions_invalidation_and_no_fallback( oriented, settings, monkeypatch ): from pigway_frame_flow.errors import FlowError oriented.save( "family", PhotoSourceInput( name="Family", kind="local", location=".", orientation="landscape" ), ) assert len(oriented.catalog("family")) == 1 monkeypatch.setattr( "pigway_frame_flow.providers.photo_sources.dimensions", lambda *a: pytest.fail("unchanged dimensions should be cached"), ) assert len(oriented.catalog("family", refresh=True)) == 1 monkeypatch.undo() Image.new("RGB", (50, 100)).save(settings.photo_root / "20240101 Day" / "wide.jpg") assert oriented.catalog("family", refresh=True) == [] with pytest.raises(FlowError): oriented.read("family") def test_orientation_validation_and_api(client, oriented): r = client.put( "/api/v1/photo-sources/family", json={ "name": "Family", "kind": "local", "location": ".", "orientation": "landscape", }, ) assert r.status_code == 200 and r.json()["orientation"] == "landscape" assert client.get("/api/v1/photo-sources/family/images").json()["total"] == 1 assert ( client.put( "/api/v1/photo-sources/family", json={ "name": "Family", "kind": "local", "location": ".", "orientation": "sideways", }, ).status_code == 422 ) assert ( client.put( "/api/v1/photo-sources/dav", json={ "name": "Remote", "kind": "webdav", "location": "https://example.com/", "orientation": "portrait", }, ).json()["error"]["code"] == "UNSUPPORTED_CAPABILITY" )