Coverage for daklib/config.py: 65%

76 statements  

« prev     ^ index     » next       coverage.py v7.6.0, created at 2026-01-04 16:18 +0000

1""" 

2Config access class 

3 

4@contact: Debian FTPMaster <ftpmaster@debian.org> 

5@copyright: 2008 Mark Hymers <mhy@debian.org> 

6@license: GNU General Public License version 2 or later 

7""" 

8 

9# This program is free software; you can redistribute it and/or modify 

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

11# the Free Software Foundation; either version 2 of the License, or 

12# (at your option) any later version. 

13 

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

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

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

17# GNU General Public License for more details. 

18 

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

20# along with this program; if not, write to the Free Software 

21# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 

22 

23################################################################################ 

24 

25# <NCommander> mhy, how about "Now with 20% more monty python references" 

26 

27################################################################################ 

28 

29import getpass 

30import grp 

31import os 

32import socket 

33from typing import TYPE_CHECKING, Any 

34 

35import apt_pkg 

36 

37if TYPE_CHECKING: 

38 from daklib.dbconn import Suite 

39 

40################################################################################ 

41 

42default_config = "/etc/dak/dak.conf" #: default dak config, defines host properties 

43 

44# suppress some deprecation warnings in squeeze related to apt_pkg 

45# module 

46import warnings 

47 

48warnings.filterwarnings("ignore", ".*apt_pkg.* is deprecated.*", DeprecationWarning) 

49 

50################################################################################ 

51 

52 

53def which_conf_file() -> str: 

54 return os.getenv("DAK_CONFIG", default_config) 

55 

56 

57class Config: 

58 """ 

59 A Config object is a singleton containing 

60 information about the DAK configuration 

61 """ 

62 

63 __shared_state: dict[str, Any] = {} 

64 

65 def __init__(self, *args, **kwargs): 

66 self.__dict__ = self.__shared_state 

67 

68 if not getattr(self, "initialised", False): 

69 self.initialised = True 

70 self._readconf() 

71 self._setup_routines() 

72 

73 def _readconf(self): 

74 apt_pkg.init() 

75 

76 self.Cnf = apt_pkg.Configuration() 

77 

78 apt_pkg.read_config_file_isc(self.Cnf, which_conf_file()) # type: ignore[attr-defined] 

79 

80 # Check whether our dak.conf was the real one or 

81 # just a pointer to our main one 

82 fqdn = socket.getfqdn() 

83 conffile = self.Cnf.get("Config::" + fqdn + "::DakConfig") 

84 if conffile: 84 ↛ 85line 84 didn't jump to line 85 because the condition on line 84 was never true

85 apt_pkg.read_config_file_isc(self.Cnf, conffile) # type: ignore[attr-defined] 

86 

87 # Read group-specific options 

88 if "ByGroup" in self.Cnf: 88 ↛ 89line 88 didn't jump to line 89 because the condition on line 88 was never true

89 bygroup = self.Cnf.subtree("ByGroup") # type: ignore[attr-defined] 

90 groups = set([os.getgid()]) 

91 groups.update(os.getgroups()) 

92 

93 for group in bygroup.list(): 

94 gid = grp.getgrnam(group).gr_gid 

95 if gid in groups: 

96 if bygroup.get(group): 

97 apt_pkg.read_config_file_isc(self.Cnf, bygroup[group]) # type: ignore[attr-defined] 

98 break 

99 

100 # Read user-specific options 

101 byuser_config_path = self.Cnf.get(f"ByUser::{getpass.getuser()}", "") 

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

103 apt_pkg.read_config_file_isc(self.Cnf, byuser_config_path) # type: ignore[attr-defined] 

104 

105 if "Include" in self.Cnf: 105 ↛ 106line 105 didn't jump to line 106 because the condition on line 105 was never true

106 for filename in self.Cnf.value_list("Include"): 

107 apt_pkg.read_config_file_isc(self.Cnf, filename) # type: ignore[attr-defined] 

108 

109 # Rebind some functions 

110 # TODO: Clean this up 

111 self.get = self.Cnf.get 

112 self.subtree = self.Cnf.subtree # type: ignore[attr-defined] 

113 self.value_list = self.Cnf.value_list 

114 self.find = self.Cnf.find 

115 self.find_b = self.Cnf.find_b 

116 self.find_i = self.Cnf.find_i # type: ignore[attr-defined] 

117 

118 def __contains__(self, name: str) -> bool: 

119 return name in self.Cnf 

120 

121 def __getitem__(self, name: str) -> str: 

122 return self.Cnf[name] 

123 

124 def __setitem__(self, name: str, value: str) -> None: 

125 self.Cnf[name] = value # type: ignore[index] 

126 

127 @staticmethod 

128 def get_db_value(name, default=None, rettype=None): 

129 from daklib.dbconn import DBConfig, DBConn, NoResultFound 

130 

131 try: 

132 res = DBConn().session().query(DBConfig).filter(DBConfig.name == name).one() 

133 except NoResultFound: 

134 return default 

135 

136 if rettype: 136 ↛ 139line 136 didn't jump to line 139 because the condition on line 136 was always true

137 return rettype(res.value) 

138 else: 

139 return res.value 

140 

141 def _setup_routines(self): 

142 """ 

143 This routine is the canonical list of which fields need to exist in 

144 the config table. If your dak instance is to work, we suggest reading it 

145 

146 Of course, what the values do is another matter 

147 """ 

148 for field in [ 

149 ("db_revision", None, int), 

150 ("defaultsuitename", "unstable", str), 

151 ("use_extfiles", None, int), 

152 ]: 

153 setattr( 

154 self, 

155 "get_%s" % field[0], 

156 lambda s=None, x=field[0], y=field[1], z=field[2]: self.get_db_value( 

157 x, y, z 

158 ), 

159 ) 

160 setattr( 

161 Config, 

162 "%s" % field[0], 

163 property(fget=getattr(self, "get_%s" % field[0])), 

164 ) 

165 

166 def get_defaultsuite(self) -> "Suite | None": 

167 from daklib.dbconn import get_suite 

168 

169 suitename = self.defaultsuitename # type: ignore[attr-defined] 

170 if not suitename: 

171 return None 

172 else: 

173 return get_suite(suitename) 

174 

175 defaultsuite = property(get_defaultsuite)