Coverage for fastblocks/adapters/images/_base.py: 100%

20 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2025-10-09 00:47 -0700

1"""Base classes and protocols for image adapters.""" 

2 

3from contextlib import suppress 

4from typing import Any, Protocol 

5from uuid import UUID 

6 

7from acb.config import AdapterBase, Settings 

8from acb.depends import depends 

9 

10 

11class ImagesBaseSettings(Settings): # type: ignore[misc] 

12 """Base settings for image adapters.""" 

13 

14 cdn_url: str | None = None 

15 media_bucket: str = "media" 

16 default_transformations: dict[str, Any] = {} 

17 lazy_loading: bool = True 

18 

19 

20class ImagesProtocol(Protocol): 

21 """Protocol for image adapter implementations.""" 

22 

23 async def upload_image(self, file_data: bytes, filename: str) -> str: ... 

24 async def get_image_url( 

25 self, image_id: str, transformations: dict[str, Any] | None = None 

26 ) -> str: ... 

27 def get_img_tag(self, image_id: str, alt: str, **attributes: Any) -> str: ... 

28 

29 

30class ImagesBase(AdapterBase): # type: ignore[misc] 

31 """Base class for image adapters.""" 

32 

33 # Required ACB 0.19.0+ metadata 

34 MODULE_ID: UUID = UUID("01937d86-4f2a-7b3c-8d9e-f3b4d3c2b1a1") # Static UUID7 

35 MODULE_STATUS = "stable" 

36 

37 def __init__(self) -> None: 

38 """Initialize image adapter.""" 

39 # Register with ACB dependency system 

40 with suppress(Exception): 

41 depends.set(self) 

42 

43 async def upload_image(self, file_data: bytes, filename: str) -> str: 

44 """Upload image and return image ID.""" 

45 raise NotImplementedError() 

46 

47 async def get_image_url( 

48 self, image_id: str, transformations: dict[str, Any] | None = None 

49 ) -> str: 

50 """Generate image URL with optional transformations.""" 

51 raise NotImplementedError() 

52 

53 def get_img_tag(self, image_id: str, alt: str, **attributes: Any) -> str: 

54 """Generate complete img tag with attributes.""" 

55 raise NotImplementedError()