Coverage for src / project_meta / project_info.py: 0%

41 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-11 21:45 +0000

1"""Project information such as name, version and description.""" 

2from __future__ import annotations 

3 

4import logging 

5from abc import ABC, abstractmethod 

6from enum import Enum, unique 

7from typing import ClassVar 

8 

9logger = logging.getLogger(__name__) 

10 

11 

12@unique 

13class _ProjectKey(Enum): 

14 """Keys for project information items and their default values.""" 

15 

16 NAME = "no-name" 

17 VERSION = "0.0.0" 

18 DESCRIPTION = "no-description" 

19 AUTHOR = "no-author" 

20 HOMEPAGE_URL = "no-homepage" 

21 

22 

23class _ProjectInfoBase(ABC): 

24 """Project information base class with singleton pattern.""" 

25 

26 _instances: ClassVar[dict[type[_ProjectInfoBase], _ProjectInfoBase]] = {} 

27 

28 def __new__(cls: type[_ProjectInfoBase], *_: object, **__: dict[object, object]) -> _ProjectInfoBase: 

29 """Singleton pattern to ensure only one instance exists. 

30 

31 :param *_: Positional arguments. 

32 :param **__: Keyword arguments. 

33 :return: Single instance of ProjectInfo. 

34 """ 

35 if cls not in cls._instances: 

36 cls._instances[cls] = super().__new__(cls) 

37 return cls._instances[cls] 

38 

39 @abstractmethod 

40 def _get_item_impl(self, project_key: _ProjectKey) -> str: 

41 """Get a project item from the implementation. 

42 

43 :param project_key: Key of the project item to retrieve. 

44 :return: Project item value. 

45 :raises ValueError: If the project key is unknown. 

46 """ 

47 

48 def _get_item(self, project_key: _ProjectKey) -> str: 

49 """Get a project item with a default fallback. 

50 

51 :param project_key: Key of the project item to retrieve. 

52 :return: Project item value or default if not found. 

53 """ 

54 try: 

55 value = self._get_item_impl(project_key) 

56 if value: 

57 return value 

58 except ValueError as err: 

59 logger.error(f"Error retrieving project key {project_key.name}: {err}") 

60 return project_key.value 

61 

62 def get_project_name(self) -> str: 

63 """Get the project name. 

64 

65 :return: Project name. 

66 """ 

67 return self._get_item(_ProjectKey.NAME) 

68 

69 def get_version(self) -> str: 

70 """Get the project version. 

71 

72 :return: Project version. 

73 """ 

74 return self._get_item(_ProjectKey.VERSION) 

75 

76 def get_description(self) -> str: 

77 """Get the project description. 

78 

79 :return: Project description. 

80 """ 

81 return self._get_item(_ProjectKey.DESCRIPTION) 

82 

83 def get_author(self) -> str: 

84 """Get the project author. 

85 

86 :return: Project author. 

87 """ 

88 return self._get_item(_ProjectKey.AUTHOR) 

89 

90 def get_homepage_url(self) -> str: 

91 """Get the project homepage URL. 

92 

93 :return: Project homepage URL. 

94 """ 

95 return self._get_item(_ProjectKey.HOMEPAGE_URL) 

96 

97 def __repr__(self) -> str: 

98 """Return a string representation of the project information. 

99 

100 :return: String with project name and version. 

101 """ 

102 return f"{self.get_project_name()} v{self.get_version()}"