Coverage for /Users/OORDCOR/Documents/code/bump-my-version/bumpversion/functions.py: 25%

42 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-15 09:15 -0600

1"""Generators for version parts.""" 

2import re 

3from typing import List, Optional, Union 

4 

5 

6class PartFunction: 

7 """Base class for a version part function.""" 

8 

9 first_value: str 

10 optional_value: str 

11 independent: bool 

12 

13 def bump(self, value: str) -> str: 

14 """Increase the value.""" 

15 raise NotImplementedError 

16 

17 

18class NumericFunction(PartFunction): 

19 """ 

20 This is a class that provides a numeric function for version parts. 

21 

22 It simply starts with the provided first_value (0 by default) and 

23 increases it following the sequence of integer numbers. 

24 

25 The optional value of this function is equal to the first value. 

26 

27 This function also supports alphanumeric parts, altering just the numeric 

28 part (e.g. 'r3' --> 'r4'). Only the first numeric group found in the part is 

29 considered (e.g. 'r3-001' --> 'r4-001'). 

30 """ 

31 

32 FIRST_NUMERIC = re.compile(r"(\D*)(\d+)(.*)") 

33 

34 def __init__(self, optional_value: Union[str, int, None] = None, first_value: Union[str, int, None] = None): 

35 if first_value is not None and not self.FIRST_NUMERIC.search(str(first_value)): 

36 raise ValueError(f"The given first value {first_value} does not contain any digit") 

37 

38 self.first_value = str(first_value or 0) 

39 self.optional_value = str(optional_value or self.first_value) 

40 

41 def bump(self, value: Union[str, int]) -> str: 

42 """Increase the first numerical value by one.""" 

43 match = self.FIRST_NUMERIC.search(str(value)) 

44 if not match: 

45 raise ValueError(f"The given value {value} does not contain any digit") 

46 part_prefix, part_numeric, part_suffix = match.groups() 

47 bumped_numeric = int(part_numeric) + 1 

48 

49 return "".join([part_prefix, str(bumped_numeric), part_suffix]) 

50 

51 

52class ValuesFunction(PartFunction): 

53 """ 

54 This is a class that provides a values list based function for version parts. 

55 

56 It is initialized with a list of values and iterates through them when 

57 bumping the part. 

58 

59 The default optional value of this function is equal to the first value, 

60 but may be otherwise specified. 

61 

62 When trying to bump a part which has already the maximum value in the list 

63 you get a ValueError exception. 

64 """ 

65 

66 def __init__( 

67 self, 

68 values: List[str], 

69 optional_value: Optional[str] = None, 

70 first_value: Optional[str] = None, 

71 ): 

72 if not values: 

73 raise ValueError("Version part values cannot be empty") 

74 

75 self._values = values 

76 

77 if optional_value is None: 

78 optional_value = values[0] 

79 

80 if optional_value not in values: 

81 raise ValueError(f"Optional value {optional_value} must be included in values {values}") 

82 

83 self.optional_value = optional_value 

84 

85 if not first_value: 

86 first_value = values[0] 

87 

88 if first_value not in values: 

89 raise ValueError(f"First value {first_value} must be included in values {values}") 

90 

91 self.first_value = first_value 

92 

93 def bump(self, value: str) -> str: 

94 """Return the item after ``value`` in the list.""" 

95 try: 

96 return self._values[self._values.index(value) + 1] 

97 except IndexError as e: 

98 raise ValueError( 

99 f"The part has already the maximum value among {self._values} and cannot be bumped." 

100 ) from e