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
« 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
4import logging
5from abc import ABC, abstractmethod
6from enum import Enum, unique
7from typing import ClassVar
9logger = logging.getLogger(__name__)
12@unique
13class _ProjectKey(Enum):
14 """Keys for project information items and their default values."""
16 NAME = "no-name"
17 VERSION = "0.0.0"
18 DESCRIPTION = "no-description"
19 AUTHOR = "no-author"
20 HOMEPAGE_URL = "no-homepage"
23class _ProjectInfoBase(ABC):
24 """Project information base class with singleton pattern."""
26 _instances: ClassVar[dict[type[_ProjectInfoBase], _ProjectInfoBase]] = {}
28 def __new__(cls: type[_ProjectInfoBase], *_: object, **__: dict[object, object]) -> _ProjectInfoBase:
29 """Singleton pattern to ensure only one instance exists.
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]
39 @abstractmethod
40 def _get_item_impl(self, project_key: _ProjectKey) -> str:
41 """Get a project item from the implementation.
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 """
48 def _get_item(self, project_key: _ProjectKey) -> str:
49 """Get a project item with a default fallback.
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
62 def get_project_name(self) -> str:
63 """Get the project name.
65 :return: Project name.
66 """
67 return self._get_item(_ProjectKey.NAME)
69 def get_version(self) -> str:
70 """Get the project version.
72 :return: Project version.
73 """
74 return self._get_item(_ProjectKey.VERSION)
76 def get_description(self) -> str:
77 """Get the project description.
79 :return: Project description.
80 """
81 return self._get_item(_ProjectKey.DESCRIPTION)
83 def get_author(self) -> str:
84 """Get the project author.
86 :return: Project author.
87 """
88 return self._get_item(_ProjectKey.AUTHOR)
90 def get_homepage_url(self) -> str:
91 """Get the project homepage URL.
93 :return: Project homepage URL.
94 """
95 return self._get_item(_ProjectKey.HOMEPAGE_URL)
97 def __repr__(self) -> str:
98 """Return a string representation of the project information.
100 :return: String with project name and version.
101 """
102 return f"{self.get_project_name()} v{self.get_version()}"