Coverage for python/lsst/dax/apdb/versionTuple.py: 40%

25 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-05-02 03:30 -0700

1# This file is part of dax_apdb. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (http://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# This software is dual licensed under the GNU General Public License and also 

10# under a 3-clause BSD license. Recipients may choose which of these licenses 

11# to use; please see the files gpl-3.0.txt and/or bsd_license.txt, 

12# respectively. If you choose the GPL option then the following text applies 

13# (but note that there is still no warranty even if you opt for BSD instead): 

14# 

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

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

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

18# (at your option) any later version. 

19# 

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

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

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

23# GNU General Public License for more details. 

24# 

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

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

27 

28from __future__ import annotations 

29 

30__all__ = [ 

31 "IncompatibleVersionError", 

32 "VersionTuple", 

33] 

34 

35from typing import NamedTuple 

36 

37 

38class IncompatibleVersionError(RuntimeError): 

39 """Exception raised when version numbers are not compatible.""" 

40 

41 

42class VersionTuple(NamedTuple): 

43 """Class representing a version number. 

44 

45 Parameters 

46 ---------- 

47 major, minor, patch : `int` 

48 Version number components 

49 """ 

50 

51 major: int 

52 minor: int 

53 patch: int 

54 

55 @classmethod 

56 def fromString(cls, versionStr: str) -> VersionTuple: 

57 """Extract version number from a string. 

58 

59 Parameters 

60 ---------- 

61 versionStr : `str` 

62 Version number in string form "X.Y.Z", all components must be 

63 present. 

64 

65 Returns 

66 ------- 

67 version : `VersionTuple` 

68 Parsed version tuple. 

69 

70 Raises 

71 ------ 

72 ValueError 

73 Raised if string has an invalid format. 

74 """ 

75 try: 

76 version = tuple(int(v) for v in versionStr.split(".")) 

77 except ValueError as exc: 

78 raise ValueError(f"Invalid version string '{versionStr}'") from exc 

79 if len(version) != 3: 

80 raise ValueError(f"Invalid version string '{versionStr}', must consist of three numbers") 

81 return cls(*version) 

82 

83 def checkCompatibility(self, database_version: VersionTuple, update: bool) -> bool: 

84 """Compare implementation schema version with schema version in 

85 database. 

86 

87 Parameters 

88 ---------- 

89 database_version : `VersionTuple` 

90 Version of the database schema. 

91 update : `bool` 

92 If True then read-write access is expected. 

93 

94 Returns 

95 ------- 

96 compatible : `bool` 

97 True if schema versions are compatible. 

98 

99 Notes 

100 ----- 

101 This method implements default rules for checking schema compatibility: 

102 

103 - if major numbers differ, schemas are not compatible; 

104 - otherwise, if minor versions are different then newer version can 

105 read schema made by older version, but cannot write into it; 

106 older version can neither read nor write into newer schema; 

107 - otherwise, different patch versions are totally compatible. 

108 """ 

109 if self.major != database_version.major: 

110 # different major versions are not compatible at all 

111 return False 

112 if self.minor != database_version.minor: 

113 # different minor versions are backward compatible for read 

114 # access only 

115 return self.minor > database_version.minor and not update 

116 # patch difference does not matter 

117 return True 

118 

119 def __str__(self) -> str: 

120 """Transform version tuple into a canonical string form.""" 

121 return f"{self.major}.{self.minor}.{self.patch}"