Coverage for /Users/coordt/Documents/code/bump-my-version/bumpversion/version_part.py: 82%

35 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-06-11 14:29 -0500

1"""Module for managing Versions and their internal parts.""" 

2 

3import re 

4from typing import Any, Dict, List, MutableMapping, Optional, Tuple 

5 

6from click import UsageError 

7 

8from bumpversion.ui import get_indented_logger 

9from bumpversion.utils import labels_for_format 

10from bumpversion.versioning.models import Version, VersionComponentSpec, VersionSpec 

11from bumpversion.versioning.serialization import parse_version, serialize 

12 

13logger = get_indented_logger(__name__) 

14 

15 

16class VersionConfig: 

17 """ 

18 Hold a complete representation of a version string. 

19 """ 

20 

21 def __init__( 

22 self, 

23 parse: str, 

24 serialize: Tuple[str], 

25 search: str, 

26 replace: str, 

27 part_configs: Optional[Dict[str, VersionComponentSpec]] = None, 

28 ): 

29 try: 

30 self.parse_regex = re.compile(parse, re.VERBOSE) 

31 except re.error as e: 

32 raise UsageError(f"--parse '{parse}' is not a valid regex.") from e 

33 

34 self.serialize_formats = serialize 

35 self.part_configs = part_configs or {} 

36 self.version_spec = VersionSpec(self.part_configs) 

37 # TODO: I think these two should be removed from the config object 

38 self.search = search 

39 self.replace = replace 

40 

41 def __repr__(self) -> str: 

42 return f"<bumpversion.VersionConfig:{self.parse_regex.pattern}:{self.serialize_formats}>" 

43 

44 def __eq__(self, other: Any) -> bool: 

45 return ( 

46 self.parse_regex.pattern == other.parse_regex.pattern 

47 and self.serialize_formats == other.serialize_formats 

48 and self.part_configs == other.part_configs 

49 and self.search == other.search 

50 and self.replace == other.replace 

51 ) 

52 

53 @property 

54 def order(self) -> List[str]: 

55 """ 

56 Return the order of the labels in a serialization format. 

57 

58 Currently, order depends on the first given serialization format. 

59 This seems like a good idea because this should be the most complete format. 

60 

61 Returns: 

62 A list of version part labels in the order they should be rendered. 

63 """ 

64 return labels_for_format(self.serialize_formats[0]) 

65 

66 def parse(self, version_string: Optional[str] = None) -> Optional[Version]: 

67 """ 

68 Parse a version string into a Version object. 

69 

70 Args: 

71 version_string: Version string to parse 

72 

73 Returns: 

74 A Version object representing the string. 

75 """ 

76 parsed = parse_version(version_string, self.parse_regex.pattern) 

77 

78 if not parsed: 78 ↛ 79line 78 didn't jump to line 79, because the condition on line 78 was never true

79 return None 

80 

81 version = self.version_spec.create_version(parsed) 

82 version.original = version_string 

83 return version 

84 

85 def serialize(self, version: Version, context: MutableMapping) -> str: 

86 """ 

87 Serialize a version to a string. 

88 

89 Args: 

90 version: The version to serialize 

91 context: The context to use when serializing the version 

92 

93 Returns: 

94 The serialized version as a string 

95 """ 

96 return serialize(version, list(self.serialize_formats), context)