1 """

2 Asset path resolution mixin for components that need to resolve asset paths.

3 """

4

5 import os

6 from typing import Optional

7

8

9 class AssetPathMixin:

10 """

11 Mixin providing asset path resolution functionality.

12

13 Requires access to self.project (typically via ApplicationStateMixin).

14 """

15

16 def resolve_asset_path(self, asset_path: str) -> Optional[str]:

17 """

18 Resolve a relative asset path to an absolute path.

19

20 Args:

21 asset_path: Relative path (e.g., "assets/photo.jpg") or absolute path

22

23 Returns:

24 Absolute path if the asset exists, None otherwise

25 """

26 if not asset_path:

27 return None

28

29 # Handle absolute paths

30 if os.path.isabs(asset_path):

31 if os.path.exists(asset_path):

32 return asset_path

33 return None

34

35 # Resolve relative path using project folder

36 project_folder = self._get_project_folder()

37 if project_folder:

38 full_path = os.path.join(project_folder, asset_path)

39 if os.path.exists(full_path):

40 return full_path

41

42 return None

43

44 def get_asset_full_path(self, relative_path: str) -> Optional[str]:

45 """

46 Get the full path for a relative asset path (without existence check).

47

48 Args:

49 relative_path: Relative path from project folder

50

51 Returns:

52 Full absolute path, or None if no project folder

53 """

54 project_folder = self._get_project_folder()

55 if project_folder and relative_path:

56 return os.path.join(project_folder, relative_path)

57 return None

58

59 def _get_project_folder(self) -> Optional[str]:

60 """

61 Get the current project folder.

62

63 Override this method if the project is accessed differently.

64 Default implementation uses self.project.folder_path.

65 """

66 if hasattr(self, "project") and self.project:

67 return getattr(self.project, "folder_path", None)

68 return None