Coverage for src/gitlabracadabra/mixins/milestones.py: 72%

50 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-03-10 17:02 +0100

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 

17import logging 

18from copy import deepcopy 

19 

20from gitlabracadabra.objects.object import GitLabracadabraObject 

21 

22logger = logging.getLogger(__name__) 

23 

24 

25class MilestonesMixin(GitLabracadabraObject): 

26 """Object with milestones.""" 

27 

28 """_process_milestones() 

29 

30 Process the milestones param. 

31 """ 

32 

33 def _process_milestones(self, param_name, param_value, *, dry_run=False, skip_save=False): 

34 assert param_name == "milestones" # noqa: S101 

35 assert not skip_save # noqa: S101 

36 unknown_milestones = self._content.get("unknown_milestones", "warn") 

37 try: 

38 current_milestones = dict( 

39 [ 

40 [current_milestone.title, current_milestone] 

41 for current_milestone in self._obj.milestones.list(all=True) 

42 ] 

43 ) 

44 except AttributeError: 

45 # https://github.com/python-gitlab/python-gitlab/pull/847 

46 logger.error( 

47 "[%s] Unable to manage milestones: %s", self._name, "group milestones requires python-gitlab >= 1.1.0" 

48 ) 

49 return 

50 target_milestones = dict( 

51 [[target_milestone["title"], deepcopy(target_milestone)] for target_milestone in param_value] 

52 ) 

53 # We first check for already existing milestones 

54 for current_milestone_title, current_milestone in sorted(current_milestones.items()): 

55 if current_milestone_title in target_milestones: 

56 for target_milestone_param_name, target_milestone_param_value in sorted( 

57 target_milestones[current_milestone_title].items() 

58 ): 

59 try: 

60 current_milestone_param_value = getattr(current_milestone, target_milestone_param_name) 

61 except AttributeError: 

62 logger.info( 

63 "[%s] NOT Changing milestone %s %s: %s -> %s (current value is not available)", 

64 self._name, 

65 current_milestone_title, 

66 target_milestone_param_name, 

67 None, 

68 target_milestone_param_value, 

69 ) 

70 continue 

71 if current_milestone_param_value is None: 71 ↛ 72line 71 didn't jump to line 72 because the condition on line 71 was never true

72 current_milestone_param_value = "" 

73 if current_milestone_param_value != target_milestone_param_value: 

74 if target_milestone_param_name == "state": 

75 target_milestone_param_name = "state_event" 

76 if target_milestone_param_value == "closed": 76 ↛ 79line 76 didn't jump to line 79 because the condition on line 76 was always true

77 target_milestone_param_value = "close" 

78 else: 

79 target_milestone_param_value = "activate" 

80 if dry_run: 80 ↛ 81line 80 didn't jump to line 81 because the condition on line 80 was never true

81 logger.info( 

82 "[%s] NOT Changing milestone %s %s: %s -> %s (dry-run)", 

83 self._name, 

84 current_milestone_title, 

85 target_milestone_param_name, 

86 current_milestone_param_value, 

87 target_milestone_param_value, 

88 ) 

89 else: 

90 logger.info( 

91 "[%s] Changing milestone %s %s: %s -> %s", 

92 self._name, 

93 current_milestone_title, 

94 target_milestone_param_name, 

95 current_milestone_param_value, 

96 target_milestone_param_value, 

97 ) 

98 setattr(current_milestone, target_milestone_param_name, target_milestone_param_value) 

99 current_milestone.save() 

100 target_milestones.pop(current_milestone_title) 

101 elif unknown_milestones in ["delete", "remove"]: 101 ↛ 107line 101 didn't jump to line 107 because the condition on line 101 was always true

102 if dry_run: 102 ↛ 103line 102 didn't jump to line 103 because the condition on line 102 was never true

103 logger.info("[%s] NOT Removing milestone %s (dry-run)", self._name, current_milestone_title) 

104 else: 

105 logger.info("[%s] Removing milestone %s", self._name, current_milestone_title) 

106 current_milestone.delete() 

107 elif unknown_milestones not in ["ignore", "skip"]: 

108 logger.warning("[%s] NOT Removing milestone: %s", self._name, current_milestone_title) 

109 # Remaining milestones 

110 for target_milestone_title, target_milestone in sorted(target_milestones.items()): 

111 if dry_run: 111 ↛ 112line 111 didn't jump to line 112 because the condition on line 111 was never true

112 logger.info( 

113 "[%s] NOT Adding milestone %s: %s -> %s (dry-run)", 

114 self._name, 

115 target_milestone_title, 

116 None, 

117 target_milestone, 

118 ) 

119 else: 

120 logger.info( 

121 "[%s] Adding milestone %s: %s -> %s", self._name, target_milestone_title, None, target_milestone 

122 ) 

123 self._obj.milestones.create(target_milestone)