Coverage for src/robotide/controller/settingcontrollers.py: 89%

461 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-05-06 10:40 +0100

1# Copyright 2008-2015 Nokia Networks 

2# Copyright 2016- Robot Framework Foundation 

3# 

4# Licensed under the Apache License, Version 2.0 (the "License"); 

5# you may not use this file except in compliance with the License. 

6# You may obtain a copy of the License at 

7# 

8# http://www.apache.org/licenses/LICENSE-2.0 

9# 

10# Unless required by applicable law or agreed to in writing, software 

11# distributed under the License is distributed on an "AS IS" BASIS, 

12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

13# See the License for the specific language governing permissions and 

14# limitations under the License. 

15 

16import re 1ab

17from itertools import chain 1ab

18 

19from .. import robotapi, utils 1ab

20from ..robotapi import ALIAS_MARKER 1ab

21from ..publish.messages import (RideImportSettingChanged, RideImportSettingRemoved, RideVariableUpdated, 1ab

22 RideItemSettingsChanged, RideImportSettingAdded) 

23from ..utils import variablematcher, unescape_newlines_and_whitespaces 1ab

24from .basecontroller import ControllerWithParent 1ab

25from .tags import Tag, ForcedTag, DefaultTag, TestTag 1ab

26 

27 

28class _SettingController(ControllerWithParent): 1ab

29 def __init__(self, parent_controller, data): 1ab

30 self._parent = parent_controller 2a # BbZb2 9b!b#b$bj k l w dc%becwb+ C Q R zb4 xbE P 'b$ (bucncfcvc' gchcycwc)bCbzcAcBcCcicocpcDb^bqcDc5 Y B x T y 0b*b+b( ,b-b.b/b:b;bc m _bd S 1b2bjcEcN kcObPbQb, - . / : ; yb= ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbob3bpbqbrbsbtbub3 K o M L G p n q s t r g X Z 0 1 H u I h i e f Fcsctcvbv z GcHcA O J Rb4bSbTb5bEbUbVbFbWb6bXbAb7bGbHbIbJbKbLbMb) * `b{b=b|bxc

31 self._data = data 2a # BbZb2 9b!b#b$bj k l w dc%becwb+ C Q R zb4 xbE P 'b$ (bucncfcvc' gchcycwc)bCbzcAcBcCcicocpcDb^bqcDc5 Y B x T y 0b*b+b( ,b-b.b/b:b;bc m _bd S 1b2bjcEcN kcObPbQb, - . / : ; yb= ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbob3bpbqbrbsbtbub3 K o M L G p n q s t r g X Z 0 1 H u I h i e f Fcsctcvbv z GcHcA O J Rb4bSbTb5bEbUbVbFbWb6bXbAb7bGbHbIbJbKbLbMb) * `b{b=b|bxc

32 self.label = self._label(self._data) 2a # BbZb2 9b!b#b$bj k l w dc%becwb+ C Q R zb4 xbE P 'b$ (bucncfcvc' gchcycwc)bCbzcAcBcCcicocpcDb^bqcDc5 Y B x T y 0b*b+b( ,b-b.b/b:b;bc m _bd S 1b2bjcEcN kcObPbQb, - . / : ; yb= ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbob3bpbqbrbsbtbub3 K o M L G p n q s t r g X Z 0 1 H u I h i e f Fcsctcvbv z GcHcA O J Rb4bSbTb5bEbUbVbFbWb6bXbAb7bGbHbIbJbKbLbMb) * `b{b=b|bxc

33 self._init(self._data) 2a # BbZb2 9b!b#b$bj k l w dc%becwb+ C Q R zb4 xbE P 'b$ (bucncfcvc' gchcycwc)bCbzcAcBcCcicocpcDb^bqcDc5 Y B x T y 0b*b+b( ,b-b.b/b:b;bc m _bd S 1b2bjcEcN kcObPbQb, - . / : ; yb= ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbob3bpbqbrbsbtbub3 K o M L G p n q s t r g X Z 0 1 H u I h i e f Fcsctcvbv z GcHcA O J Rb4bSbTb5bEbUbVbFbWb6bXbAb7bGbHbIbJbKbLbMb) * `b{b=b|bxc

34 

35 def _init(self, data): 1ab

36 raise NotImplementedError 

37 

38 def _label(self, data): 1ab

39 label = data.setting_name 2a Bbj k l w dc%becucncfcvc' gcDb^bqc*b+b( ,b-b.b/b:b;bc m _bd S 1b2bEckc, - . / : ; yb= ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbob3bpbqbrbsbtbub3 K o M L G p n q s t r g X Z 0 1 H u I h i e f vbv z A O J Rb4bSbTb5bEbUbVbFbWb6bXbAb7bGbHbIbJbKbLbMb

40 if label.startswith('['): 2a Bbj k l w dc%becucncfcvc' gcDb^bqc*b+b( ,b-b.b/b:b;bc m _bd S 1b2bEckc, - . / : ; yb= ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbob3bpbqbrbsbtbub3 K o M L G p n q s t r g X Z 0 1 H u I h i e f vbv z A O J Rb4bSbTb5bEbUbVbFbWb6bXbAb7bGbHbIbJbKbLbMb

41 return label[1:-1] 2a Bbj k l w dcDb*b+b( ,b-b.b/b:b;bc m _bd S 1b2b, - . / : ; = ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbub3 K o M L G p n q s t r g X Z 0 1 H u I h i e f vbv z A O J Rb4bSbTb5bEbUbVbFbWb6bXbAb7bGbHbIbJbKbLbMb

42 return label 2a j k l w %becucncfcvc' gc^bqcc m Eckc, - . / : ; yb= ? @ D U F V [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbob3bpbqbrbsbtbub3 n q s t r g X Z 0 1 H u I e f vbv z A O J

43 

44 @property 1ab

45 def _value(self): 1ab

46 return [v.replace('|', '\\|') for v in self.as_list()[1:]] 2dcRcecYbScgc*b+b( ,b-b.b/b:bc d D U F V W h i e f

47 

48 @property 1ab

49 def value(self): 1ab

50 value = self._value 2*b+b( ,b-b.b/b:bc d D U F V W h i e f

51 if self._data.comment: 2*b+b( ,b-b.b/b:bc d D U F V W h i e f

52 value.pop() 1cd

53 return ' | '.join(value) 2*b+b( ,b-b.b/b:bc d D U F V W h i e f

54 

55 @property 1ab

56 def display_value(self): 1ab

57 return ' | ' .join(self._value) 2dcRcecYbScgc

58 

59 def as_list(self): 1ab

60 # print(f"\nDEBUG: _SettingController enter as_list") 

61 return self._data.as_list() 2dc%bRcecYbScgc*b+b( ,b-b.b/b:b;bc d , - . / : ; yb= ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbob3bpbqbrbsbtbub3 h i e f vb

62 

63 @property 1ab

64 def comment(self): 1ab

65 return self._data.comment 2j k l w Mcc m d S h i e f

66 

67 @property 1ab

68 def keyword_name(self): 1ab

69 return '' 

70 

71 def contains_keyword(self, name): 1ab

72 istring = isinstance(name, str) 2%b, - . / : ; yb= ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbob3bpbqbrbsbtbub3 vb

73 # print(f"DEBUG: settingcontrollers.py _SettingController contains_keyword: item={self} search=" 

74 # f"{name}") 

75 matcher = name.match if not istring else lambda i: utils.eq(i, name) 2%b, - . / : ; yb= ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbob3bpbqbrbsbtbub3 vb

76 return self._contains_keyword(matcher) 2%b, - . / : ; yb= ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbob3bpbqbrbsbtbub3 vb

77 

78 def _contains_keyword(self, matcher_function): 1ab

79 return any(matcher_function(item or '') for item in self.as_list()) 2%b, - . / : ; yb= ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbob3bpbqbrbsbtbub3 vb

80 

81 def contains_variable(self, name): 1ab

82 return variablematcher.value_contains_variable(self.value, name) 1DUFVW

83 

84 @property 1ab

85 def is_set(self): 1ab

86 return self._data.is_set() 2j k l w RcScc m d S h i e f

87 

88 def set_from(self, other): 1ab

89 if other.is_set: 1jklwcmdShief

90 self.set_value(other.value) 1cdhief

91 self.set_comment(other.comment) 1jklwcmdShief

92 

93 def set_value(self, value): 1ab

94 if self._changed(value): 2BbYc?b8bNcOcPcQc}b~bacbcccYb% TcIcJcKcLc@b[b]bDb( c d K o M L G p n q s t r g u h i e f v z GbHbIbJbKbLbMb

95 self._set(value) 2Bb?b8bNcOcPc}b~bacbcccYb% IcJcKc@b[b]bDb( c d K o M L G p n q s t r g u h i e f v z GbHbIbJbKbLbMb

96 self.mark_dirty() 2Bb?b8bNcOcPc}b~bacbcccYb% IcJcKc@b[b]bDb( c d K o M L G p n q s t r g u h i e f v z GbHbIbJbKbLbMb

97 RideItemSettingsChanged(item=self._parent).publish() 2Bb?b8bNcOcPc}b~bacbcccYb% IcJcKc@b[b]bDb( c d K o M L G p n q s t r g u h i e f v z GbHbIbJbKbLbMb

98 

99 def set_comment(self, comment): 1ab

100 if comment != self.comment: 100 ↛ exitline 100 didn't return from function 'set_comment' because the condition on line 100 was always true2j k l w Mcc m d S h i e f

101 if not isinstance(comment, robotapi.Comment): 2j k l w Mcc m d S h i e f

102 comment = robotapi.Comment(comment) 2Mcc d

103 self._data.comment = comment 2j k l w Mcc m d S h i e f

104 self.mark_dirty() 2j k l w Mcc m d S h i e f

105 

106 def notify_value_changed(self, old_name=None, new_name=None): 1ab

107 self._parent.notify_settings_changed(old_name) 16789!3nqstrguvz

108 

109 def clear(self): 1ab

110 self._data.reset() 2UcVcA

111 self.mark_dirty() 2UcVcA

112 RideItemSettingsChanged(item=self._parent).publish() 2UcVcA

113 

114 def _changed(self, value): 1ab

115 return value != self._data.value 2Yc?b8bNcOcPcc d h i e f

116 

117 def _set(self, value): 1ab

118 self._data.value = value 2?b8bNcOcPcc d h i e f

119 

120 @staticmethod 1ab

121 def _split_from_separators(value): 1ab

122 return utils.split_value(value) 2BbQc}b~bacbcccYb% TcIcJcKcDb( c d K o M L G p n q s t r g u h i e f v z GbHbIbJbKbLbMb

123 

124 

125class DocumentationController(_SettingController): 1ab

126 _regexps = (re.compile(r'(\\+)r\\n'), 1ab

127 re.compile(r'(\\+)n'), 

128 re.compile(r'(\\+)r'), 

129 re.compile(r'(\\+) ')) 

130 

131 def _init(self, doc): 1ab

132 self._doc = doc 2a j k l w dc^bqcc m _bd S 1b2bkc, - . / : ; yb= ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbob3bpbqbrbsbtbub3 h i e f vbRbSbTbEbUbVbFbWbXbAb

133 

134 @property 1ab

135 def value(self): 1ab

136 return self._doc.value 2Zc0c?b8bc d kcD U F V W h i e f RbSbTbEbUbVbFbWbXbAb

137 

138 def contains_keyword(self, name): 1ab

139 return False 2, - . / : ; yb= ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbob3bpbqbrbsbtbub3 vb

140 

141 def _get_editable_value(self): 1ab

142 return unescape_newlines_and_whitespaces(self.value) 2Zc?b8b

143 

144 def _set_editable_value(self, value): 1ab

145 self.set_value(self._escape_newlines_and_leading_hash(value)) 2?b8b

146 

147 editable_value = property(_get_editable_value, _set_editable_value) 1ab

148 

149 @property 1ab

150 def visible_value(self): 1ab

151 return utils.html_format(utils.unescape(self.value)) 20c

152 

153 @staticmethod 1ab

154 def _escape_newlines_and_leading_hash(item): 1ab

155 for newline in ('\r\n', '\n', '\r'): 2?b8b

156 item = item.replace(newline, '\\n') 2?b8b

157 if item.strip().startswith('#'): 2?b8b

158 item = '\\' + item 28b

159 return item 2?b8b

160 

161 

162class FixtureController(_SettingController): 1ab

163 

164 def _init(self, fixture): 1ab

165 self._fixture = fixture 2a j k l w %bec^bqcc m _bd S 1b2bkc, - . / : ; yb= ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbub3 h i e f vb

166 

167 @property 1ab

168 def keyword_name(self): 1ab

169 return self._fixture.name 

170 

171 def replace_keyword(self, new_name, old_value=None): 1ab

172 # print(f"DEBUG: settingcontrollers.py replace_keyword new_name={new_name} existing name={self._fixture.name}" 

173 # f"\nold_value={old_value}") 

174 if self._fixture.name == old_value: 16793

175 self._fixture.name = new_name 1679

176 else: 

177 for idx, argument in enumerate(self._fixture.args): 13

178 if argument == old_value: 13

179 self._fixture.args[idx] = new_name 13

180 self.mark_dirty() 16793

181 

182 def _changed(self, value): 1ab

183 name, args = self._parse(value) 2Qc}b~bacbcccYbc d e f

184 return self._fixture.name != name or self._fixture.args != args 2Qc}b~bacbcccYbc d e f

185 

186 def _set(self, value): 1ab

187 name, args = self._parse(value) 2}b~bacbcccYbc d e f

188 self._fixture.name = name 2}b~bacbcccYbc d e f

189 self._fixture.args = args 2}b~bacbcccYbc d e f

190 

191 def _parse(self, value): 1ab

192 value = self._split_from_separators(value) 2Qc}b~bacbcccYbc d e f

193 return (value[0], value[1:]) if value else ('', []) 2Qc}b~bacbcccYbc d e f

194 

195 

196class TagsController(_SettingController): 1ab

197 

198 def _init(self, tags): 1ab

199 self.tags = tags 2a j k l w ' ^bqc;bc m _bd S 1b2bkc, - . / : ; yb= ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbub3 n q s t r g X Z 0 1 H u I h i e f vbv z A O J Rb4bSbTb5bEbUbVbFbWb6bXbAb7b

200 

201 def empty_tag(self): 1ab

202 return Tag(None, controller=self) 1nq

203 

204 def _changed(self, value): 1ab

205 return self.tags.value != self._split_from_separators(value) 2% TcIcJcKcc d n q s t r g u e f v z

206 

207 def set_from(self, other): 1ab

208 if other.is_set and other.tags.value is not None: 1jklwcmdShief

209 self.set_value(other.value) 1cdef

210 self.set_comment(other.comment) 1jklwcmdShief

211 

212 def _set(self, value): 1ab

213 self.tags.value = self._split_from_separators(value) 2% IcJcKcc d n q s t r g u e f v z

214 

215 def add(self, tag): 1ab

216 if self.tags.value is None: 2w Wc;bn q s t r g X Z 0 1 H u I A J

217 self.tags.value = [] 2w ;bn q s t r g X Z 0 1 H u I A J

218 tag.set_index(len(self.tags.value)) 2w Wc;bn q s t r g X Z 0 1 H u I A J

219 self.tags.value.append(tag.name) 2w Wc;bn q s t r g X Z 0 1 H u I A J

220 

221 def remove(self, tag): 1ab

222 if tag in self.tags.value: 

223 self.tags.value.remove(tag) 

224 

225 def __iter__(self): 1ab

226 forced = self._parent.force_tags 2j k l w Nb% ' c m d S n q s t r g X Z 0 1 H u I h i e f v z A O J Rb4bSbTb5bEbUbVbFbWb6bXbAb7b

227 test_tags = self._parent.test_tags 2j k l w Nb% ' c m d S n q s t r g X Z 0 1 H u I h i e f v z A O J Rb4bSbTb5bEbUbVbFbWb6bXbAb7b

228 if self.tags.value is None: 2j k l w Nb% ' c m d S n q s t r g X Z 0 1 H u I h i e f v z A O J Rb4bSbTb5bEbUbVbFbWb6bXbAb7b

229 return chain(forced, self._parent.default_tags, test_tags).__iter__() 1jklw'cmdSnXZ01hivzAO

230 if len(self.tags.value) == 0: 2Nb% c d n q s t r g H u I e f v z A J Rb4bSbTb5bEbUbVbFbWb6bXbAb7b

231 return chain(forced, test_tags, [Tag('', controller=self)]) 2n r RbSbTbUbVbWbXbAb

232 own_tags = (Tag(t, index, self) 2Nb% c d q s t r g H u I e f v z A J 4b5bEbFb6bAb7b

233 for index, t in enumerate(self.tags.value)) 

234 return chain(forced, test_tags, own_tags).__iter__() 2Nb% c d q s t r g H u I e f v z A J 4b5bEbFb6bAb7b

235 

236 @property 1ab

237 def is_set(self): 1ab

238 return any(self) 2j k l w Nbc m d S h i e f

239 

240 @property 1ab

241 def display_value(self): 1ab

242 return ' | ' .join(tag.name.replace('|', '\\|') for tag in self) 2Nb% '

243 

244 

245class DefaultTagsController(TagsController): 1ab

246 

247 def empty_tag(self): 1ab

248 return DefaultTag(None, controller=self) 

249 

250 def __iter__(self): 1ab

251 if self.tags.value is None: 2j k l w Nb% ' c m n X v z A O

252 return [].__iter__() 2j k l Nb% ' c m v z A O

253 return (DefaultTag(t, index, self) 1wnXv

254 for index, t in enumerate(self.tags.value)).__iter__() 

255 

256 

257class ForceTagsController(TagsController): 1ab

258 

259 def empty_tag(self): 1ab

260 return ForcedTag(None, controller=self) 

261 

262 def __iter__(self): 1ab

263 return self._recursive_gather_from(self.parent, []).__iter__() 2j k l w Nb% ' c m n q s t r g X Z 0 1 H u I e f v z A O J

264 

265 def __eq__(self, other): 1ab

266 if self is other: 266 ↛ 267line 266 didn't jump to line 267 because the condition on line 266 was never true1g

267 return True 

268 if other is None: 268 ↛ 269line 268 didn't jump to line 269 because the condition on line 268 was never true1g

269 return False 

270 if not isinstance(other, self.__class__): 270 ↛ 272line 270 didn't jump to line 272 because the condition on line 270 was always true1g

271 return False 1g

272 return self.tags == other.tags 

273 

274 def _recursive_gather_from(self, obj, result): 1ab

275 if obj is None: 2j k l w Nb% ' c m n q s t r g X Z 0 1 H u I e f v z A O J

276 return result 1jklwcmnqstrgXZ01HuIefvzAOJ

277 try: 2j k l w Nb% ' c m n q s t r g X Z 0 1 H u I e f v z A O J

278 force_tags = obj.setting_table.force_tags 2j k l w Nb% ' c m n q s t r g X Z 0 1 H u I e f v z A O J

279 except AttributeError: # In the case of a .resource file, there is no Forced Tags fields 2Nb% '

280 return result 2Nb% '

281 # print(f"DEBUG: SettingsController _recursive_gather_from force_tags={force_tags}, obj.parent={obj.parent}") 

282 return self._recursive_gather_from( 1jklwcmnqstrgXZ01HuIefvzAOJ

283 obj.parent, 

284 self._gather_from_data(force_tags, obj.force_tags) + result) 

285 

286 @staticmethod 1ab

287 def _gather_from_data(tags, parent): 1ab

288 if tags.value is None: 1jklwcmnqstrgXZ01HuIefvzAOJ

289 return [] 1jklwcmnqstrgXZ01HuIvzAOJ

290 return [ForcedTag(t, index, parent) 1gZ01ef

291 for index, t in enumerate(tags.value)] 

292 

293 

294class TestTagsController(TagsController): 1ab

295 

296 def empty_tag(self): 1ab

297 return TestTag(None, controller=self) 

298 

299 def __iter__(self): 1ab

300 return self._recursive_gather_from(self.parent, []).__iter__() 1jklcmnqstrgHuIvzAOJ

301 

302 def __eq__(self, other): 1ab

303 if self is other: 

304 return True 

305 if other is None: 

306 return False 

307 if not isinstance(other, self.__class__): 

308 return False 

309 return self.tags == other.tags 

310 

311 def _recursive_gather_from(self, obj, result): 1ab

312 if obj is None: 1jklcmnqstrgHuIvzAOJ

313 return result 1jklcmnqstrgHuIvzAOJ

314 try: 1jklcmnqstrgHuIvzAOJ

315 test_tags = obj.setting_table.test_tags 1jklcmnqstrgHuIvzAOJ

316 except AttributeError: # In the case of a .resource file, there is no Test Tags fields 

317 return result 

318 # print(f"DEBUG: SettingsController _recursive_gather_from force_tags={force_tags}, obj.parent={obj.parent}") 

319 return self._recursive_gather_from( 1jklcmnqstrgHuIvzAOJ

320 obj.parent, 

321 self._gather_from_data(test_tags, obj.test_tags) + result) 

322 

323 @staticmethod 1ab

324 def _gather_from_data(tags, parent): 1ab

325 if tags.value is None: 325 ↛ 327line 325 didn't jump to line 327 because the condition on line 325 was always true1jklcmnqstrgHuIvzAOJ

326 return [] 1jklcmnqstrgHuIvzAOJ

327 return [TestTag(t, index, parent) 

328 for index, t in enumerate(tags.value)] 

329 

330 

331class TimeoutController(_SettingController): 1ab

332 

333 def _init(self, timeout): 1ab

334 self._timeout = timeout 2a j k l w gc^bc m _bd S 1b2b, - . / : ; yb= ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbub3 h i e f vb

335 

336 def _changed(self, value): 1ab

337 val, msg = self._parse(value) 2Lc@b[b]bc d

338 return self._timeout.value != val or self._timeout.message != msg 2Lc@b[b]bc d

339 

340 def _set(self, value): 1ab

341 value, message = self._parse(value) 2@b[b]bc d

342 self._timeout.value = value 2@b[b]bc d

343 self._timeout.message = message 2@b[b]bc d

344 

345 @staticmethod 1ab

346 def _parse(value): 1ab

347 parts = value.split('|', 1) 2Lc@b[b]bc d

348 val = parts[0].strip() if parts else '' 2Lc@b[b]bc d

349 msg = parts[1].strip() if len(parts) == 2 else '' 2Lc@b[b]bc d

350 return val, msg 2Lc@b[b]bc d

351 

352 

353class TemplateController(_SettingController): 1ab

354 

355 def _init(self, template): 1ab

356 self._template = template 2j k l w ^bc m _b, - . / : ; yb= ? @ D U F V W [ ] ^ _ ` 6 7 8 9 ! { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbub3 e f vb

357 

358 def _set(self, value): 1ab

359 _SettingController._set(self, value) 1c

360 self._parent.notify_steps_changed() 1c

361 

362 def clear(self): 1ab

363 _SettingController.clear(self) 

364 self._parent.notify_steps_changed() 

365 

366 @property 1ab

367 def keyword_name(self): 1ab

368 return self._template.value 

369 

370 def replace_keyword(self, new_name, old_name=None): 1ab

371 _ = old_name 18!

372 self._template.value = new_name 18!

373 self.mark_dirty() 18!

374 

375 

376class ArgumentsController(_SettingController): 1ab

377 

378 def _init(self, args): 1ab

379 self._args = args 2BbDb*b+b( ,b-b.b/b:bd S 1b2bD U F V W K o M L G p h i GbHbIbJbKbLbMb

380 

381 def _changed(self, value): 1ab

382 return self._args.value != self._split_from_separators(value) 2BbDb( d K o M L G p h i GbHbIbJbKbLbMb

383 

384 def _set(self, value): 1ab

385 self._args.value = self._split_from_separators(value) 2BbDb( d K o M L G p h i GbHbIbJbKbLbMb

386 self._parent.notify_settings_changed() 2BbDb( d K o M L G p h i GbHbIbJbKbLbMb

387 

388 def clear(self): 1ab

389 _SettingController.clear(self) 

390 self._parent.notify_settings_changed() 

391 

392 

393class ReturnValueController(_SettingController): 1ab

394 

395 def _init(self, return_): 1ab

396 self._return = return_ 2a d S 1b2bD U F V W h i

397 

398 def _label(self, data): 1ab

399 return 'Return Value' 2a d S 1b2bD U F V W h i

400 

401 def _changed(self, value): 1ab

402 return self._return.value != self._split_from_separators(value) 1dhi

403 

404 def _set(self, value): 1ab

405 self._return.value = self._split_from_separators(value) 1dhi

406 

407 

408class MetadataController(_SettingController): 1ab

409 

410 def _init(self, meta): 1ab

411 self._meta = meta 2ucncfcvc

412 

413 @property 1ab

414 def name(self): 1ab

415 return self._meta.name 2nc

416 

417 @property 1ab

418 def value(self): 1ab

419 return self._meta.value 2nc

420 

421 def set_value(self, name=None, value=None): 1ab

422 self._meta.name = name 2fc

423 self._meta.value = value 2fc

424 self._parent.mark_dirty() 2fc

425 

426 

427class VariableController(_SettingController): 1ab

428 

429 def _init(self, var): 1ab

430 self.var = var 2a hcycwc)bCbzcAcBcCcicocpcDcObPbQbFcsctcGcHc`b{b=b|bxc

431 

432 def _label(self, data): 1ab

433 return '' 2a hcycwc)bCbzcAcBcCcicocpcDcObPbQbFcsctcGcHc`b{b=b|bxc

434 

435 def __ne__(self, other): 1ab

436 return not (self == other) # This cannot be compared with != 2ic`b{b=b|b

437 

438 @property 1ab

439 def name(self): 1ab

440 return self.var.name 2hcycwc)bCbzcAcBcCcicocpcDcObPbQb`b{b=b|bxc

441 

442 @property 1ab

443 def value(self): 1ab

444 return self.var.value 2)bocpcObPbQb

445 

446 @property 1ab

447 def comment(self): 1ab

448 return self.var.comment 2ocpcObPbQb

449 

450 @property 1ab

451 def data(self): 1ab

452 return self._data 2a wcObPbQbGcHc

453 

454 @property 1ab

455 def index(self): 1ab

456 return self.parent.index(self) 2hcCbocpcObPbQb`b{b=b|bxc

457 

458 @staticmethod 1ab

459 def get_local_variables(): 1ab

460 return {} 

461 

462 def set_value(self, name=None, value=None): 1ab

463 if isinstance(value, str): 2)bCb

464 value = [value] 2)bCb

465 self.var.name = name 2)bCb

466 self.var.value = value 2)bCb

467 self._parent.mark_dirty() 2)bCb

468 

469 def has_data(self): 1ab

470 return self._data.has_data() 2a Fc

471 

472 def delete(self): 1ab

473 self._parent.remove_var(self) 2ObPbQb

474 

475 def notify_value_changed(self): 1ab

476 RideVariableUpdated(item=self).publish() 

477 

478 def notify_variable_added(self): 1ab

479 self.parent.notify_variable_added(self) 

480 

481 def validate_name(self, new_name): 1ab

482 if variablematcher.is_scalar_variable(self.name): 

483 return self.parent.validate_scalar_variable_name(new_name, self) 

484 if variablematcher.is_dict_variable(self.name): 

485 return self.parent.validate_dict_variable_name(new_name, self) 

486 return self.parent.validate_list_variable_name(new_name, self) 

487 

488 def move_up(self): 1ab

489 return self._parent.move_up(self.index) 

490 

491 def move_down(self): 1ab

492 return self._parent.move_down(self.index) 

493 

494 def __eq__(self, other): 1ab

495 if self is other: 2hcCbicObPbQbsc1cXctc`b{b=b|b

496 return True 21c

497 if other.__class__ != self.__class__: 2hcCbicObPbQbscXctc`b{b=b|b

498 return False 2icXc`b{b=b|b

499 return self.var == other.var 2hcCbObPbQbsctc=b

500 

501 def __hash__(self): 1ab

502 return hash(self.var) + 1 

503 

504 

505def import_controller(parent, import_): 1ab

506 if import_.type == 'Resource': 2a # Zb2 9b!b#b$bwb+ C Q R zb4 xbE P 'b$ (b5 Y B x T y 0bN D K o M L G p ) *

507 return ResourceImportController(parent, import_) 2a # $bwb+ C Q R zb4 xbE P $ 5 Y B x T y N D K o M L G p ) *

508 elif import_.type == 'Library': 2a # Zb2 9b!b#bwb+ C Q R zb4 xbE P 'b(b0bD

509 return LibraryImportController(parent, import_) 2a # Zb2 9b!b#bwb+ C Q R zb4 xbE P 'b0b

510 return VariablesImportController(parent, import_) 2a xb(bD

511 

512 

513class _ImportController(_SettingController): 1ab

514 

515 def __init__(self, parent_controller, data): 1ab

516 super().__init__(parent_controller, data) 2a # Zb2 9b!b#b$bwb+ C Q R zb4 xbE P 'b$ (b5 Y B x T y 0bjcN D K o M L G p ) *

517 self.is_resource = None 2a # Zb2 9b!b#b$bwb+ C Q R zb4 xbE P 'b$ (b5 Y B x T y 0bjcN D K o M L G p ) *

518 

519 def _init(self, import_): 1ab

520 self._import = import_ 2a # Zb2 9b!b#b$bwb+ C Q R zb4 xbE P 'b$ (b5 Y B x T y 0bjcN D K o M L G p ) *

521 self.type = self._import.type 2a # Zb2 9b!b#b$bwb+ C Q R zb4 xbE P 'b$ (b5 Y B x T y 0bjcN D K o M L G p ) *

522 

523 def _label(self, data): 1ab

524 return data.type 2a # Zb2 9b!b#b$bwb+ C Q R zb4 xbE P 'b$ (b5 Y B x T y 0bjcN D K o M L G p ) *

525 

526 @property 1ab

527 def name(self): 1ab

528 return self._import.name 2a wbC Q R zb4 xbE P 5 Y B x T y 2c3c4clc5crc6c0b7cmc8cN #c$c) 9c

529 

530 @property 1ab

531 def alias(self): 1ab

532 return self._import.alias or '' 2wb+ C Q R

533 

534 @property 1ab

535 def args(self): 1ab

536 return self._import.args or [] 2wb+ C Q R

537 

538 @property 1ab

539 def display_value(self): 1ab

540 value = self.args + ([ALIAS_MARKER, self.alias] if self.alias else []) 1+

541 return ' | '.join(value) 1+

542 

543 @property 1ab

544 def dirty(self): 1ab

545 return self._parent.dirty 

546 

547 def has_error(self): 1ab

548 return False 

549 

550 def get_imported_controller(self): 1ab

551 return None 1a#F

552 

553 def set_value(self, name, args=None, alias=''): 1ab

554 self._import.name = name 12CQREBxy

555 self._import.args = utils.split_value(args or []) 12CQREBxy

556 self._import.alias = alias 12CQREBxy

557 self._parent.mark_dirty() 12CQREBxy

558 self.publish_edited() 12CQREBxy

559 self.import_loaded_or_modified() 12CQREBxy

560 return self 12CQREBxy

561 

562 def import_loaded_or_modified(self): 1ab

563 self._parent.notify_imports_modified() 12CQREBxy

564 if not self.is_resource: 564 ↛ 566line 564 didn't jump to line 566 because the condition on line 564 was always true12CQREBxy

565 return 12CQREBxy

566 self._parent.resource_import_modified(self.name) 

567 

568 def remove(self): 1ab

569 self.parent.remove_import_data(self._import) 1No

570 

571 def publish_added(self): 1ab

572 RideImportSettingAdded( 2a Zb2 9b!b#bzb4 xb'b$ (bK o M L G p *

573 datafile=self.datafile_controller, 

574 import_controller=self, type=self.type.lower()).publish() 

575 

576 def publish_edited(self): 1ab

577 RideImportSettingChanged( 12CQREBxy

578 datafile=self.datafile_controller, 

579 import_controller=self, type=self.type.lower()).publish() 

580 

581 def publish_removed(self): 1ab

582 RideImportSettingRemoved(datafile=self.datafile_controller, 2Zb2 P N o p

583 import_controller=self, 

584 type=self.type.lower()).publish() 

585 

586 

587class ResourceImportController(_ImportController): 1ab

588 is_resource = True 1ab

589 _resolved_import = False 1ab

590 _previous_imported_controller = None 1ab

591 

592 def __init__(self, parent_controller, data): 1ab

593 super().__init__(parent_controller, data) 2a # $bwb+ C Q R zb4 xbE P $ 5 Y B x T y jcN D K o M L G p ) *

594 self._imported_resource_controller = None 2a # $bwb+ C Q R zb4 xbE P $ 5 Y B x T y jcN D K o M L G p ) *

595 

596 def set_value(self, name, args=None, alias=''): 1ab

597 self._previous_imported_controller = self.get_imported_controller() 1CEBxy

598 self.unresolve() 1CEBxy

599 _ImportController.set_value(self, name, args, alias) 1CEBxy

600 

601 def get_imported_controller(self): 1ab

602 if not self._resolved_import: 2a # C 4 E P $ 5 Y B x T y lcrcmcN F K o M L G p ) * !c

603 self._imported_resource_controller = self.parent.resource_file_controller_factory.find_with_import( 2a # C 4 E P $ 5 Y B x T y lcrcmcN F K o M L G p ) *

604 self._import) 

605 if self._imported_resource_controller: 2a # C 4 E P $ 5 Y B x T y lcrcmcN F K o M L G p ) *

606 self._imported_resource_controller.add_known_import(self) 2a # $ 5 Y B x T y lcmcN F K o L G p )

607 self._resolved_import = True 2a # C 4 E P $ 5 Y B x T y lcrcmcN F K o M L G p ) *

608 return self._imported_resource_controller 2a # C 4 E P $ 5 Y B x T y lcrcmcN F K o M L G p ) * !c

609 

610 def has_error(self): 1ab

611 # un-resolve before checking import errors 

612 self.unresolve() 2lcrcmc

613 return self.get_imported_controller() is None 2lcrcmc

614 

615 def publish_added(self): 1ab

616 # Resolve the import <-> ResourceFileController link 

617 self.get_imported_controller() 14$KoMLGp*

618 _ImportController.publish_added(self) 14$KoMLGp*

619 

620 def publish_removed(self): 1ab

621 self._previous_imported_controller = self.get_imported_controller() 1PNop

622 # Unresolve the import <-> ResourceFileController link 

623 self.unresolve() 1PNop

624 self._prevent_resolve() 1PNop

625 _ImportController.publish_removed(self) 1PNop

626 

627 def _prevent_resolve(self): 1ab

628 self._resolved_import = True 1PNop

629 self._imported_resource_controller = None 1PNop

630 

631 def get_previous_imported_controller(self): 1ab

632 return self._previous_imported_controller 1Gp

633 

634 def unresolve(self): 1ab

635 if self._resolved_import and self._imported_resource_controller: 2C E P 5 Y B x T y lcrcmcN o p

636 self._imported_resource_controller.remove_known_import(self) 15YBxTyNop

637 self._resolved_import = False 2C E P 5 Y B x T y lcrcmcN o p

638 

639 def contains_filename(self, filename): 1ab

640 return self.name.endswith(filename) 2Y B ) 9c

641 

642 def change_name(self, old_name, new_name): 1ab

643 # print(f"DEBUG: settingcontrollers.py ResourceImportController change_name ENTER\n" 

644 # f"old_name={old_name} new_name={new_name}") 

645 if self.contains_filename(old_name): 1YB

646 self.set_value(self.name[:-len(old_name)] + new_name) 1B

647 else: 

648 # If original result has changed and this import relies on 

649 # variables, can't know if import is still resolved 

650 self.unresolve() 1Y

651 

652 def change_format(self, cformat): 1ab

653 if self._has_format(): 1xTy

654 self.set_value(utils.replace_extension(self.name, cformat)) 1xy

655 else: 

656 self.unresolve() 1T

657 

658 def _has_format(self): 1ab

659 parts = self.name.rsplit('.', 1) 1xTy

660 if len(parts) == 1: 1xTy

661 return False 1T

662 return parts[-1].lower() in ['txt', 'tsv', 'robot', 'resource'] 1xy

663 

664 

665class LibraryImportController(_ImportController): 1ab

666 is_resource = False 1ab

667 

668 def has_error(self): 1ab

669 return not self.parent.parent.is_library_import_ok(self._data) 22c3c4c5c0b7c

670 

671 

672class VariablesImportController(_ImportController): 1ab

673 is_resource = False 1ab

674 

675 def has_error(self): 1ab

676 return not self.parent.parent.is_variables_import_ok(self._data) 26c8c