Coverage for src/gitlabracadabra/gitlab/group_cache.py: 74%

1#

2# Copyright (C) 2019-2025 Mathieu Parent <math.parent@gmail.com>

3#

4# This program is free software: you can redistribute it and/or modify

5# it under the terms of the GNU Lesser General Public License as published by

6# the Free Software Foundation, either version 3 of the License, or

7# (at your option) any later version.

8#

9# This program is distributed in the hope that it will be useful,

10# but WITHOUT ANY WARRANTY; without even the implied warranty of

11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

12# GNU Lesser General Public License for more details.

13#

14# You should have received a copy of the GNU Lesser General Public License

15# along with this program. If not, see <http://www.gnu.org/licenses/>.

16

17

18 from __future__ import annotations

19

20 from typing import TYPE_CHECKING

21

22 from gitlab.exceptions import GitlabGetError

23 from requests import codes

24

25 if TYPE_CHECKING: 25 ↛ 26line 25 didn't jump to line 26 because the condition on line 25 was never true

26 from gitlabracadabra.gitlab.pygitlab import PyGitlab

27

28

29 class GroupCache:

30 """Groups mapping cache.

31

32 indexed by id and full path.

33 """

34

35 def __init__(self, connection: PyGitlab) -> None:

36 """Initialize a Python-Gitlab wrapper.

37

38 Args:

39 connection: A GitlabConnection/PyGitlab.

40 """

41 self._connection = connection

42 self._path2id: dict[str, int | None] = {}

43 self._id2path: dict[int, str | None] = {}

44

45 def map_group(self, group_id: int, group_full_path: str) -> None:

46 """Map group id and full path.

47

48 Args:

49 group_id: Group id.

50 group_full_path: Group full path.

51 """

52 self._id2path[group_id] = group_full_path

53 self._path2id[group_full_path] = group_id

54

55 def full_path_from_id(self, group_id: int) -> str | None:

56 """Get group full path from id.

57

58 Args:

59 group_id: Group id.

60

61 Returns:

62 Group full path.

63

64 Raises:

65 GitlabGetError: Any HTTP error other than 404.

66 """

67 if group_id not in self._id2path: 67 ↛ 76line 67 didn't jump to line 76 because the condition on line 67 was always true

68 obj_manager = self._connection.pygitlab.groups

69 try:

70 group = obj_manager.get(group_id)

71 self.map_group(group.id, group.full_path)

72 except GitlabGetError as err:

73 if err.response_code != codes["not_found"]:

74 raise

75 self._id2path[group_id] = None

76 return self._id2path[group_id]

77

78 def id_from_full_path(self, group_full_path: str) -> int | None:

79 """Get group id from full path.

80

81 Args:

82 group_full_path: Group full path.

83

84 Returns:

85 Group id.

86

87 Raises:

88 GitlabGetError: Any HTTP error other than 404.

89 """

90 if group_full_path not in self._path2id: 90 ↛ 99line 90 didn't jump to line 99 because the condition on line 90 was always true

91 obj_manager = self._connection.pygitlab.groups

92 try:

93 group = obj_manager.get(group_full_path)

94 self.map_group(group.id, group.full_path)

95 except GitlabGetError as err:

96 if err.response_code != codes["not_found"]: 96 ↛ 97line 96 didn't jump to line 97 because the condition on line 96 was never true

97 raise

98 self._path2id[group_full_path] = None

99 return self._path2id[group_full_path]