Coverage for src/robotide/namespace/namespace.py: 91%

473 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 operator 1aI

17import os 1aI

18import re 1aI

19import sys 1aI

20import tempfile 1aI

21from itertools import chain 1aI

22from multiprocessing import shared_memory 1aI

23from robotide.lib.compat.parsing.language import Language 1aI

24 

25from .. import robotapi, utils 1aI

26from ..publish import PUBLISHER, RideSettingsChanged, RideLogMessage 1aI

27from ..robotapi import VariableFileSetter 1aI

28from ..spec.iteminfo import (TestCaseUserKeywordInfo, ResourceUserKeywordInfo, VariableInfo, UserKeywordInfo, 1aI

29 ArgumentInfo, LibraryKeywordInfo, BlockKeywordInfo) 

30from .cache import LibraryCache, ExpiringCache 1aI

31from .resourcefactory import ResourceFactory 1aI

32from .embeddedargs import EmbeddedArgsHandler 1aI

33 

34 

35class Namespace(object): 1aI

36 

37 def __init__(self, settings): 1aI

38 self._context_factory = None 2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbX

39 self.settings = settings 2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbX

40 self._library_manager = None 2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbX

41 self._content_assist_hooks = [] 2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbX

42 self._update_listeners = set() 2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbX

43 self._init_caches() 2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbX

44 self._set_pythonpath() 2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbX

45 self._words_cache = set() 2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbX

46 PUBLISHER.subscribe(self._setting_changed, RideSettingsChanged) 2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbX

47 

48 def _init_caches(self): 1aI

49 self._lib_cache = LibraryCache( 2a NbAbBbwbxbCbybKbLbMbObPbQbc RbSbX

50 self.settings, self.update, self._library_manager) 

51 self._resource_factory = ResourceFactory(self.settings) 2a NbAbBbwbxbCbybKbLbMbObPbQbc RbSbX

52 self._retriever = DatafileRetriever(self._lib_cache, 2a NbAbBbwbxbCbybKbLbMbObPbQbc RbSbX

53 self._resource_factory, self) 

54 self._context_factory = _RetrieverContextFactory() 2a NbAbBbwbxbCbybKbLbMbObPbQbc RbSbX

55 

56 def _set_pythonpath(self): 1aI

57 """Add user configured paths to PYTHONAPATH. 

58 """ 

59 path_idx = 0 2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbpcqcrcsctcucvcwcxcX

60 dp = os.getenv('RIDE_DOC_PATH') 2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbpcqcrcsctcucvcwcxcX

61 if not dp: 2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbpcqcrcsctcucvcwcxcX

62 doc_paths = ['.'] 

63 else: 

64 doc_paths = dp.split(',') 2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbpcqcrcsctcucvcwcxcX

65 for path in self.settings.get('pythonpath', []): 65 ↛ 66line 65 didn't jump to line 66 because the loop on line 65 never started2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbpcqcrcsctcucvcwcxcX

66 if os.path.isdir(path): 

67 doc_paths.append(path.replace('/', os.sep)) 

68 if path not in sys.path: 

69 normalized = path.replace('/', os.sep) 

70 sys.path.insert(path_idx, normalized) 

71 path_idx += 1 

72 RideLogMessage(u'Inserted \'{0}\' to sys.path.'.format(normalized)).publish() 

73 os.environ['RIDE_DOC_PATH'] = ",".join(doc_paths) 2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbpcqcrcsctcucvcwcxcX

74 

75 def _setting_changed(self, message): 1aI

76 section, setting = message.keys 2a UcVcNbdcAbBbwbxbCbybKbLbMbObPbG H F HbIbJbQbRbSbpcqcrcsctcucvcwcxcWcXcYcZc0c1c2c3c

77 if section == '' and setting == 'pythonpath': 2a UcVcNbdcAbBbwbxbCbybKbLbMbObPbG H F HbIbJbQbRbSbpcqcrcsctcucvcwcxcWcXcYcZc0c1c2c3c

78 for p in set(message.old).difference(message.new): 78 ↛ 79line 78 didn't jump to line 79 because the loop on line 78 never started2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbpcqcrcsctcucvcwcxc

79 if p in sys.path: 

80 sys.path.remove(p) 

81 self._set_pythonpath() 2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbpcqcrcsctcucvcwcxc

82 

83 def update_exec_dir_global_var(self, exec_dir): 1aI

84 _VariableStash.global_variables['${EXECDIR}'] = exec_dir 2a dc

85 self._context_factory.reload_context_global_vars() 2a dc

86 

87 def update_cur_dir_global_var(self, cur_dir): 1aI

88 dp = os.getenv('RIDE_DOC_PATH') 2a GcHcIcJcKcJ L M N O b dcibmbnbobDbubE ecd ~bfcgchcicjcR e h i m n o p q r s t j u 0 c v w x y z f A B k l g 4c

89 parent_cur_dir=os.path.dirname(os.path.abspath(cur_dir)) 2a GcHcIcJcKcJ L M N O b dcibmbnbobDbubE ecd ~bfcgchcicjcR e h i m n o p q r s t j u 0 c v w x y z f A B k l g 4c

90 if dp: 90 ↛ 94line 90 didn't jump to line 94 because the condition on line 90 was always true2a GcHcIcJcKcJ L M N O b dcibmbnbobDbubE ecd ~bfcgchcicjcR e h i m n o p q r s t j u 0 c v w x y z f A B k l g

91 if cur_dir not in dp: 2a GcHcIcJcKcJ L M N O b dcibmbnbobDbubE ecd ~bfcgchcicjcR e h i m n o p q r s t j u 0 c v w x y z f A B k l g

92 os.environ['RIDE_DOC_PATH'] = dp + f", {cur_dir}, {parent_cur_dir}" 2a GcHcIcJcKcJ b dcibDbE i 0

93 else: 

94 os.environ['RIDE_DOC_PATH'] = f"{cur_dir}, {parent_cur_dir}" 

95 _VariableStash.global_variables['${CURDIR}'] = cur_dir 2a GcHcIcJcKcJ L M N O b dcibmbnbobDbubE ecd ~bfcgchcicjcR e h i m n o p q r s t j u 0 c v w x y z f A B k l g

96 self._context_factory.reload_context_global_vars() 2a GcHcIcJcKcJ L M N O b dcibmbnbobDbubE ecd ~bfcgchcicjcR e h i m n o p q r s t j u 0 c v w x y z f A B k l g

97 

98 def set_library_manager(self, library_manager): 1aI

99 self._library_manager = library_manager 2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbX

100 self._lib_cache.set_library_manager(library_manager) 2a NbAbBbwbxbCbybKbLbMbObPbQbRbSbX

101 

102 def update(self, *args): 1aI

103 _ = args 2a Z J L M N O LcMcwbxbybUbU V W mcNcOcPc[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ P Q Vb~ G H F HbIbJbd ac

104 self._retriever.expire_cache() 2a Z J L M N O LcMcwbxbybUbU V W mcNcOcPc[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ P Q Vb~ G H F HbIbJbd ac

105 self._context_factory = _RetrieverContextFactory() 2a Z J L M N O LcMcwbxbybUbU V W mcNcOcPc[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ P Q Vb~ G H F HbIbJbd ac

106 for listener in self._update_listeners: 2a Z J L M N O LcMcwbxbybUbU V W mcNcOcPc[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ P Q Vb~ G H F HbIbJbd ac

107 listener() 2a Z J L M N O LcMcU V W mcNcOcPc[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ P Q Vb~ G H F HbIbJbd

108 

109 def resource_filename_changed(self, old_name, new_name): 1aI

110 self._resource_factory.resource_filename_changed(old_name, new_name) 2a AbBbwbxbCbyb

111 

112 def reset_resource_and_library_cache(self): 1aI

113 self._init_caches() 2a NbAbBbwbxbCbybKbLbMbObPbQbc RbSb

114 

115 def register_update_listener(self, listener): 1aI

116 self._update_listeners.add(listener) # append(listener) # DEBUG .add(listener) 2a Z 9c!c#c$c%c'c(c)c*c+c,c-c.c/c:c;c=c?c@c[cU V W mcbb#b[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T 9b~ G H F HbIbJbE

117 

118 def unregister_update_listener(self, listener): 1aI

119 if listener in self._update_listeners: 119 ↛ exitline 119 didn't return from function 'unregister_update_listener' because the condition on line 119 was always true2Z U V W mc

120 self._update_listeners.remove(listener) 2Z U V W mc

121 

122 def clear_update_listeners(self): 1aI

123 self._update_listeners.clear() # = list() # DEBUG .clear() 

124 

125 def register_content_assist_hook(self, hook): 1aI

126 self._content_assist_hooks.append(hook) 1X

127 

128 def get_all_keywords(self, testsuites): 1aI

129 kws = set() 2a kcR pb

130 kws.update(self._get_default_keywords()) 2a kcR pb

131 kws.update(self._retriever.get_keywords_from_several(testsuites)) 2a kcR pb

132 return kws 2a kcR pb

133 

134 def _get_default_keywords(self): 1aI

135 return self._lib_cache.get_default_keywords() 2a d cbabkcR pbi m n o p q r s t j u 0 c v w x y z f A B S k l X

136 

137 def get_suggestions_for(self, controller, start): 1aI

138 if not controller: 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d ~bzbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

139 return [] 2d ~b

140 datafile = controller.datafile 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

141 ctx = self._context_factory.ctx_for_controller(controller) 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

142 sugs = set() # self._words_cache or 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

143 # print(f"DEBUG: namespace.py Namespace get_suggestions_for ENTER start={start} {datafile=} {ctx=} {sugs=}") 

144 while start and start[-1] in [']', '}', '=', ',']: 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

145 start = start[:-1] 2D jb| _ ebkb} C ` dbfbgbhblbb 2 zbqbrbsbtb: /

146 sugs.update(self._get_suggestions_from_hooks(datafile, start)) 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

147 if self._blank(start) or not self._looks_like_variable(start): 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

148 sugs.update(self._variable_suggestions(controller, start, ctx)) 2d cbabi m n o p q r s t j u 0 c v w x y z f A B S k l X

149 sugs.update(self._keyword_suggestions(datafile, start, ctx)) 2d cbabi m n o p q r s t j u 0 c v w x y z f A B S k l X

150 else: 

151 sugs.update(self._variable_suggestions(controller, start, ctx)) 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbtbabY ; : = ? , / - @ .

152 # print(f"DEBUG: namespace.py Namespace get_suggestions_for BEFORE CONTENT start={start} {sugs=}") 

153 if not self._looks_like_variable(start): # Search in content 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

154 for v in ['${', '@{', '&{', '%{', '$']: 2d cbabi m n o p q r s t j u 0 c v w x y z f A B S k l X

155 sugs.update(self._content_suggestions(f'{v}{utils.normalize(start)}')) 2d cbabi m n o p q r s t j u 0 c v w x y z f A B S k l X

156 else: 

157 sugs.update(self._content_suggestions(f'{utils.normalize(start, suffixless=True)}')) 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbtbabY ; : = ? , / - @ .

158 # print(f"DEBUG: namespace.py Namespace get_suggestions_for FROM CONTENT start={start} {sugs=}") 

159 sugs_list = list(sugs) 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

160 sugs_list.sort() 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

161 # print(f"DEBUG: namespace.py Namespace get_suggestions_for RETURN {sugs_list=}") 

162 return sugs_list 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

163 

164 def _get_suggestions_from_hooks(self, datafile, start): 1aI

165 sugs = [] 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

166 for hook in self._content_assist_hooks: 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

167 sugs.extend(hook(datafile, start)) 1X

168 return sugs 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

169 

170 def get_all_cached_library_names(self): 1aI

171 return self._retriever.get_all_cached_library_names() 25c

172 

173 @staticmethod 1aI

174 def _blank(start): 1aI

175 return start == '' 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

176 

177 @staticmethod 1aI

178 def _looks_like_variable(start): 1aI

179 return len(start) == 1 and start[0] in ['$', '@', '&', '%'] \ 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

180 or (len(start) >= 2 and start[:2] in ['${', '@{', '&{', '%{']) \ 

181 or len(start) >= 2 and start[0] == '$' 

182 

183 def _variable_suggestions(self, controller, start, ctx): 1aI

184 self._add_kw_arg_vars(controller, ctx.vars) 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

185 variables = self._retriever.get_variables_from( 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

186 controller.datafile, ctx) 

187 sugs = (v for v in variables if v.name_matches(start)) 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

188 return sugs 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

189 

190 def _content_suggestions(self, start): 1aI

191 sugs = set() 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

192 for v in self._words_cache: 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

193 if isinstance(v, (TestCaseUserKeywordInfo, ResourceUserKeywordInfo, UserKeywordInfo, 193 ↛ 195line 193 didn't jump to line 195 because the condition on line 193 was never true1d

194 LibraryKeywordInfo, BlockKeywordInfo)): 

195 if v.name.lower().startswith(start.lower()): 

196 sugs.add(v.name) 

197 elif isinstance(v, (VariableInfo, ArgumentInfo)): 197 ↛ 198line 197 didn't jump to line 198 because the condition on line 197 was never true1d

198 if v.name_matches(start): 

199 # print(f"DEBUG: namespace.py Namespace _content_suggestions SUGGESTION from VARIABLE {v.name=}") 

200 sugs.add(v.name) 

201 elif (v.lower().startswith(start.lower()) or v.strip('$&@%{[()]}=').lower() 1d

202 .startswith(start.strip('$&@%{[()]}=').lower())): 

203 # print(f"DEBUG: namespace.py Namespace _content_suggestions SUGGESTION from STRING {v=}" 

204 # f"\n v.lower().startswith(start.lower() ={v.lower().startswith(start.lower())}") 

205 sugs.add(v) 1d

206 return sugs 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

207 

208 @staticmethod 1aI

209 def _add_kw_arg_vars(controller, variables): 1aI

210 for name, value in controller.get_local_variables().items(): 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

211 variables.set_argument(name, value) 2qbrbsbvbcbtbabY ; i m : n o p q r s t j u = c v w x y z ? A B , k - @ . l

212 

213 def _keyword_suggestions(self, datafile, start, ctx): 1aI

214 start_normalized = utils.normalize(start) 2d cbabi m n o p q r s t j u 0 c v w x y z f A B S k l X

215 all_kws = chain(self._get_default_keywords(), 2d cbabi m n o p q r s t j u 0 c v w x y z f A B S k l X

216 self._retriever.get_keywords_from(datafile, ctx)) 

217 return (sug for sug in all_kws 2d cbabi m n o p q r s t j u 0 c v w x y z f A B S k l X

218 if sug.name_begins_with(start_normalized) or 

219 sug.longname_begins_with(start_normalized)) 

220 

221 def get_resources(self, datafile, language=None): 1aI

222 return self._retriever.get_resources_from(datafile, language=language) 2a Gb

223 

224 def get_resource(self, path, directory='', report_status=True): 1aI

225 return self._resource_factory.get_resource( 2a ]c^c_c`cKbLbG H F HbIbJbac

226 directory, path, 

227 report_status=report_status) 

228 

229 def find_resource_with_import(self, imp): 1aI

230 ctx = self._context_factory.ctx_for_datafile(imp.parent.parent) 2a 4bAbBbwbxbCbybRcScTcUb5bG H F HbIbJbWbac

231 return self._resource_factory.get_resource_from_import(imp, ctx) 2a 4bAbBbwbxbCbybRcScTcUb5bG H F HbIbJbWbac

232 

233 def new_resource(self, path, directory=''): 1aI

234 return self._resource_factory.new_resource(directory, path) 2{c|cMbG H F HbIbJb

235 

236 def find_user_keyword(self, datafile, kw_name): 1aI

237 kw = self.find_keyword(datafile, kw_name) 2a D jb!bZb[bZ | ,b_ eb0b1b2bbcJ L M N O } C ` dbfbgbhb3bb 2 { U V W 1 G H F e 8b6bh

238 return kw if isinstance(kw, UserKeywordInfo) else None 2a D jb!bZb[bZ | ,b_ eb0b1b2bbcJ L M N O } C ` dbfbgbhb3bb 2 { U V W 1 G H F e 8b6bh

239 

240 def is_user_keyword(self, datafile, kw_name): 1aI

241 return bool(self.find_user_keyword(datafile, kw_name)) 2a D jb!bZb[bZ | ,b_ eb0b1b2bbcJ L M N O } C ` dbfbgbhb3bb 2 { U V W 1 G H F 6bh

242 

243 def find_library_keyword(self, datafile, kw_name): 1aI

244 kw = self.find_keyword(datafile, kw_name) 2a Zb[bZ ,b_ eb0b1b2bJ L M N O C ` dbfbgbhb3bb 2 { G H F 7bccg

245 return kw if kw and kw.is_library_keyword() else None 2a Zb[bZ ,b_ eb0b1b2bJ L M N O C ` dbfbgbhb3bb 2 { G H F 7bccg

246 

247 def is_library_import_ok(self, datafile, imp): 1aI

248 return self._retriever.is_library_import_ok( 2ibmbnbobDbub

249 datafile, imp, self._context_factory.ctx_for_datafile(datafile)) 

250 

251 def is_variables_import_ok(self, datafile, imp): 1aI

252 return self._retriever.is_variables_import_ok( 2EbFb

253 datafile, imp, self._context_factory.ctx_for_datafile(datafile)) 

254 

255 def find_keyword(self, datafile, kw_name): 1aI

256 if not kw_name: 2a D jb!bZb[bZ | ,b_ eb0b1b2bbckbJ L M N O } C ` dbfbgbhblb3bb 2 { U V W bb#byc$bzcAc-b.b/b:bK ^b5b_b`b[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T %b'b(b)b9bBc*b]b+b;b=b?bP Q Vb~ G H F E e 8b7bcc6bh g

257 return None 2,bdb

258 from ..controller.cellinfo import UPPERCASE_KWS 2a D jb!bZb[bZ | ,b_ eb0b1b2bbckbJ L M N O } C ` dbfbgbhblb3bb 2 { U V W bb#byc$bzcAc-b.b/b:bK ^b5b_b`b[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T %b'b(b)b9bBc*b]b+b;b=b?bP Q Vb~ G H F E e 8b7bcc6bh g

259 casesensitive = (kw_name.upper() != kw_name and kw_name.upper() in UPPERCASE_KWS) 2a D jb!bZb[bZ | ,b_ eb0b1b2bbckbJ L M N O } C ` dbfbgbhblb3bb 2 { U V W bb#byc$bzcAc-b.b/b:bK ^b5b_b`b[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T %b'b(b)b9bBc*b]b+b;b=b?bP Q Vb~ G H F E e 8b7bcc6bh g

260 kwds = self._retriever.get_keywords_cached(datafile, self._context_factory, caseless=not casesensitive) 2a D jb!bZb[bZ | ,b_ eb0b1b2bbckbJ L M N O } C ` dbfbgbhblb3bb 2 { U V W bb#byc$bzcAc-b.b/b:bK ^b5b_b`b[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T %b'b(b)b9bBc*b]b+b;b=b?bP Q Vb~ G H F E e 8b7bcc6bh g

261 # print(f"DEBUG: namespace.py Namespace find_keyword will GET kw_name=={kw_name} casesensitive={casesensitive}") 

262 return kwds.get(kw_name, origin=datafile) 2a D jb!bZb[bZ | ,b_ eb0b1b2bbckbJ L M N O } C ` dbfbgbhblb3bb 2 { U V W bb#byc$bzcAc-b.b/b:bK ^b5b_b`b[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T %b'b(b)b9bBc*b]b+b;b=b?bP Q Vb~ G H F E e 8b7bcc6bh g

263 

264 def is_library_keyword(self, datafile, kw_name): 1aI

265 return bool(self.find_library_keyword(datafile, kw_name)) 2a Zb[bZ ,b_ eb0b1b2bJ L M N O C ` dbfbgbhb3bb 2 { G H F 7bccg

266 

267 def keyword_details(self, datafile, name): 1aI

268 # print(f"DEBUG: namespace.py Namespace keyword_details ENTER will look for name=={name} " 

269 # f"in datafile={datafile.source}") 

270 kw = self.find_keyword(datafile, name) 

271 return kw.details if kw else None 

272 

273 def update_words_cache(self, words_list:list, reset=False): 1aI

274 if reset: 274 ↛ 275line 274 didn't jump to line 275 because the condition on line 274 was never true1ad

275 self._words_cache.clear() 

276 return 

277 self._words_cache.update(set(words_list)) 1ad

278 

279 

280class _RetrieverContextFactory(object): 1aI

281 def __init__(self): 1aI

282 self._context_cache = {} 2a Z J L M N O NbLcMcAbBbwbxbCbybUbKbLbMbObPbU V W mcNcOcPc[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ P Q Vb~ G H F HbIbJbd Qbc RbSbXbX ac

283 

284 def ctx_for_controller(self, controller): 1aI

285 if controller not in self._context_cache: 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

286 self._context_cache[controller] = RetrieverContext() 2D | _ } C ` b 2 d zbqbrbsbvbcbtbabY j 0 c f , S k / - . l X

287 self._context_cache[controller.datafile 2D | _ } C ` b 2 d zbqbrbsbvbcbtbabY j 0 c f , S k / - . l X

288 ] = self._context_cache[controller] 

289 return self._context_cache[controller] 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

290 

291 def ctx_for_datafile(self, datafile): 1aI

292 if datafile not in self._context_cache: 2a 4bD Z J L M N O C b { AbBbwbxbCbybibmbnbRcobScEbDbubTcFbUbU V W bbK 5b[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F HbIbJbE e h g XbWbac

293 ctx = RetrieverContext() 2a 4bD Z J L M N O C b { AbBbwbxbCbybibDbUbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F HbIbJbE e h g XbWb

294 ctx.set_variables_from_datafile_variable_table(datafile) 2a 4bD Z J L M N O C b { AbBbwbxbCbybibDbUbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F HbIbJbE e h g XbWb

295 self._context_cache[datafile] = ctx 2a 4bD Z J L M N O C b { AbBbwbxbCbybibDbUbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F HbIbJbE e h g XbWb

296 return self._context_cache[datafile] 2a 4bD Z J L M N O C b { AbBbwbxbCbybibmbnbRcobScEbDbubTcFbUbU V W bbK 5b[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F HbIbJbE e h g XbWbac

297 

298 def reload_context_global_vars(self): 1aI

299 for retrieve_context in self._context_cache.values(): 2a GcHcIcJcKcJ L M N O b dcibmbnbobDbubE ecd ~bfcgchcicjcR e h i m n o p q r s t j u 0 c v w x y z f A B k l g

300 retrieve_context.vars.load_builtin_global_vars() 2a J L M N O b ibmbnbobDbubE ecd ~bfcgchcicjce h i m n o p q r s t j u 0 c v w x y z f A B k l g

301 

302 

303class RetrieverContext(object): 1aI

304 def __init__(self): 1aI

305 self.vars = _VariableStash() 2a 4bD Z | _ J L M N O } C ` b 2 { AbBbwbxbCbybibDbUbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F HbIbJbE d zbqbrbsbvbcbtbabR e h pbY j 0 c f , S k / - . l g GbXbX Wb

306 self.parsed = set() 2a 4bD Z | _ J L M N O } C ` b 2 { AbBbwbxbCbybibDbUbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F HbIbJbE d zbqbrbsbvbcbtbabR e h pbY j 0 c f , S k / - . l g GbXbX Wb

307 

308 def set_variables_from_datafile_variable_table(self, datafile): 1aI

309 self.vars.set_from_variable_table(datafile.variable_table) 2a 4bD jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 { AbBbwbxbCbybibmbnbobEbDbubFbUbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F HbIbJbE d zbqbrbsbvbcbtbabR e h pbY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g GbXbX Wb

310 

311 def replace_variables(self, text): 1aI

312 return self.vars.replace_variables(text) 2a J L M N O b ibmbnbobEbDbubFbK E d R e h Y ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g

313 

314 def allow_going_through_resources_again(self): 1aI

315 """Resets the parsed resources cache. 

316 

317 Normally all resources that have been handled are added to 'parsed' and 

318 then not handled again, to prevent looping forever. If this same 

319 context is used for going through the resources again, this method 

320 should be called first. 

321 """ 

322 self.parsed = set() 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d cbabR e h pbi m n o p q r s t j u 0 c v w x y z f A B S k l g X

323 

324 

325class _VariableStash(object): 1aI

326 # Global variables copied from robot.variables 

327 global_variables = { 1aI

328 '${:}': os.pathsep, 

329 '${/}': os.sep, 

330 '${CURDIR}': '.', 

331 '${DEBUG_FILE}': '', 

332 '${EMPTY}': '', 

333 '${EXECDIR}': os.path.abspath('.'), 

334 '${False}': False, 

335 '${KEYWORD_MESSAGE}': '', 

336 '${KEYWORD_STATUS}': '', 

337 '${LOG_FILE}': '', 

338 '${LOG_LEVEL}': '', 

339 '${\\n}': os.linesep, 

340 '${None}': None, 

341 '${null}': None, 

342 '${OUTPUT_DIR}': '', 

343 '${OUTPUT_FILE}': '', 

344 '${PREV_TEST_MESSAGE}': '', 

345 '${PREV_TEST_NAME}': '', 

346 '${PREV_TEST_STATUS}': '', 

347 '${REPORT_FILE}': '', 

348 '${SPACE}': ' ', 

349 '${SUITE_DOCUMENTATION}': '', 

350 '${SUITE_MESSAGE}': '', 

351 '${SUITE_METADATA}': '', 

352 '${SUITE_NAME}': '', 

353 '${SUITE_SOURCE}': '', 

354 '${SUITE_STATUS}': '', 

355 '${TEMPDIR}': os.path.normpath(tempfile.gettempdir()), 

356 '${TEST_DOCUMENTATION}': '', 

357 '${TEST_MESSAGE}': '', 

358 '${TEST_NAME}': '', 

359 '${TEST_STATUS}': '', 

360 '@{TEST_TAGS}': [], 

361 '${True}': True 

362 } 

363 

364 ARGUMENT_SOURCE = object() 1aI

365 

366 def __init__(self): 1aI

367 self._vars = robotapi.RobotVariables() 2a 4bD Z | _ J L M N O } C ` b 2 { AbBbwbxbCbybibDbUbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F HbIbJbE d zbqbrbsbvbcbtbabR e h pbY j 0 c f , S k / - . l g Gb{bCcDcEcFc@b|b}bTbXbX Wb

368 self._sources = {} 2a 4bD Z | _ J L M N O } C ` b 2 { AbBbwbxbCbybibDbUbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F HbIbJbE d zbqbrbsbvbcbtbabR e h pbY j 0 c f , S k / - . l g Gb{bCcDcEcFc@b|b}bTbXbX Wb

369 self.load_builtin_global_vars() 2a 4bD Z | _ J L M N O } C ` b 2 { AbBbwbxbCbybibDbUbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F HbIbJbE d zbqbrbsbvbcbtbabR e h pbY j 0 c f , S k / - . l g Gb{bCcDcEcFc@b|b}bTbXbX Wb

370 

371 def load_builtin_global_vars(self): 1aI

372 for k, v in self.global_variables.items(): 2a 4bD Z | _ J L M N O } C ` b 2 { AbBbwbxbCbybibmbnbobDbubUbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F HbIbJbE ecd ~bfcgchcicjczbqbrbsbvbcbtbabR e h pbY i m n o p q r s t j u 0 c v w x y z f A B , S k / - . l g Gb{bCcDcEcFc@b|b}bTbXbX Wb

373 self.set(k, v, 'built-in') 2a 4bD Z | _ J L M N O } C ` b 2 { AbBbwbxbCbybibmbnbobDbubUbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F HbIbJbE ecd ~bfcgchcicjczbqbrbsbvbcbtbabR e h pbY i m n o p q r s t j u 0 c v w x y z f A B , S k / - . l g Gb{bCcDcEcFc@b|b}bTbXbX Wb

374 

375 def set(self, name, value, source): 1aI

376 self._vars[name] = value 2a 4bD jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 { AbBbwbxbCbybibmbnbobEbDbubFbUbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F HbIbJbE ecd ~bfcgchcicjczbqbrbsbvbcbtbabR e h pbY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g Gb{bCcDcEcFc@b|b}bTbXbX Wb

377 self._sources[name[2:-1]] = source 2a 4bD jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 { AbBbwbxbCbybibmbnbobEbDbubFbUbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F HbIbJbE ecd ~bfcgchcicjczbqbrbsbvbcbtbabR e h pbY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g Gb{bCcDcEcFc@b|b}bTbXbX Wb

378 

379 def set_argument(self, name, value): 1aI

380 self.set(name, value, self.ARGUMENT_SOURCE) 2qbrbsbvbcbtbabY ; i m : n o p q r s t j u = c v w x y z ? A B , k - @ . l

381 

382 def replace_variables(self, value): 1aI

383 try: 2a 4bJ L M N O b 2 AbBbwbxbCbybibmbnbRcobScEbDbubTcFbUbU V W K 5bT P Q G H F HbIbJbE d R e h pbY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g Gb{bCcDcEcFc|b}bXbWbac

384 return self._vars.replace_scalar(value) 2a 4bJ L M N O b 2 AbBbwbxbCbybibmbnbRcobScEbDbubTcFbUbU V W K 5bT P Q G H F HbIbJbE d R e h pbY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g Gb{bCcDcEcFc|b}bXbWbac

385 except robotapi.DataError: 

386 return self._vars.replace_string(value, ignore_errors=True) 

387 

388 def set_from_variable_table(self, variable_table): 1aI

389 # print("DEBUG: set_from_variable_table = %s \n" % list(variable_table)) 

390 reader = robotapi.VariableTableReader() 2a 4bD jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 { AbBbwbxbCbybibmbnbobEbDbubFbUbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F HbIbJbE d zbqbrbsbvbcbtbabR e h pbY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g Gb{b|b}bTbXbX Wb

391 # print("DEBUG: set_from_variable_table reader %s \n" % reader) 

392 for variable in variable_table: 2a 4bD jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 { AbBbwbxbCbybibmbnbobEbDbubFbUbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F HbIbJbE d zbqbrbsbvbcbtbabR e h pbY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g Gb{b|b}bTbXbX Wb

393 try: 2a D jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 AbBbwbxbCbybibmbnbobEbubFbU V W K T P Q G H F HbIbE d R e h pbY ; i m : n o p q r s t j u = c v w x y z ? f A B , k / - @ . l g Gb{b|b}bTbXbWb

394 if variable.name not in self._vars.store: 394 ↛ 392line 394 didn't jump to line 392 because the condition on line 394 was always true2a D jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 AbBbwbxbCbybibmbnbobEbubFbU V W K T P Q G H F HbIbE d R e h pbY ; i m : n o p q r s t j u = c v w x y z ? f A B , k / - @ . l g Gb{b|b}bTbXbWb

395 _, value = reader.get_name_and_value( 2a D jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 AbBbwbxbCbybibmbnbobEbubFbU V W K T P Q G H F HbIbE d R e h pbY ; i m : n o p q r s t j u = c v w x y z ? f A B , k / - @ . l g Gb{b|b}bTbXbWb

396 variable.name, 

397 variable.value, 

398 variable.report_invalid_syntax 

399 ) 

400 # print("DEBUG: inside variable.name= %s \n" % variable.name) 

401 self.set(variable.name, value.resolve(self._vars), 2a D jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 AbBbwbxbCbybibmbnbobEbubFbU V W K T P Q G H F HbIbE d R e h pbY ; i m : n o p q r s t j u = c v w x y z ? f A B , k / - @ . l g Gb{b|b}bTbXbWb

402 variable_table.source) 

403 except (robotapi.VariableError, robotapi.DataError, Exception): 2a R e Y ; i m : n o p q r s t u = c v w x y z ? f A B @ GbTb

404 if robotapi.is_var(variable.name): 2a R e Y ; i m : n o p q r s t u = c v w x y z ? f A B @ GbTb

405 val = self._empty_value_for_variable_type(variable.name) 2R e Y ; i m : n o p q r s t u = c v w x y z ? f A B @ GbTb

406 self.set(variable.name, val, variable_table.source) 2R e Y ; i m : n o p q r s t u = c v w x y z ? f A B @ GbTb

407 

408 @staticmethod 1aI

409 def _empty_value_for_variable_type(name): 1aI

410 if name[0] == '$': 2R e Y ; i m : n o p q r s t u = c v w x y z ? f A B @ GbTb

411 return '' 2R e Y ; i m : n o p q r s t u = c v w x y z ? f A B @ GbTb

412 if name[0] == '@': 412 ↛ 413line 412 didn't jump to line 413 because the condition on line 412 was never true2R e Y ; i m : n o p q r s t u = c v w x y z ? f A B @ Gb

413 return [] 

414 return {} 2R e Y ; i m : n o p q r s t u = c v w x y z ? f A B @ Gb

415 

416 def set_from_file(self, varfile_path, args): 1aI

417 from ..robotapi import Variables 2a ibmbnbobEbubFbK d R e h Y ; i m : n o p q r s t j u = c v w x y z ? f A B , S k / - @ . l g

418 from robotide.lib.robot.variables.store import VariableStore 2a ibmbnbobEbubFbK d R e h Y ; i m : n o p q r s t j u = c v w x y z ? f A B , S k / - @ . l g

419 class Dummy: 2a ibmbnbobEbubFbK d R e h Y ; i m : n o p q r s t j u = c v w x y z ? f A B , S k / - @ . l g

420 language='En' 2a ibmbnbobEbubFbK d R e h Y ; i m : n o p q r s t j u = c v w x y z ? f A B , S k / - @ . l g

421 parent = Dummy() 2a ibmbnbobEbubFbK d R e h Y ; i m : n o p q r s t j u = c v w x y z ? f A B , S k / - @ . l g

422 store = VariableStore(Variables(parent, "")) 2a ibmbnbobEbubFbK d R e h Y ; i m : n o p q r s t j u = c v w x y z ? f A B , S k / - @ . l g

423 # print(f"namespace._VariableStash.set_from_file: variable_path {varfile_path} " 

424 # f"args {args}") 

425 try: 2a ibmbnbobEbubFbK d R e h Y ; i m : n o p q r s t j u = c v w x y z ? f A B , S k / - @ . l g

426 vars_from_file = VariableFileSetter(store) 2a ibmbnbobEbubFbK d R e h Y ; i m : n o p q r s t j u = c v w x y z ? f A B , S k / - @ . l g

427 resulting_vars = vars_from_file._import_if_needed(varfile_path, args) 2a ibmbnbobEbubFbK d R e h Y ; i m : n o p q r s t j u = c v w x y z ? f A B , S k / - @ . l g

428 except (robotapi.DataError, Exception) as e: 2ibmbnbobEbubFbR e Y ; i m : n o p q r s t u = c v w x y z ? f A B @

429 # print(f"namespace._VariableStash.set_from_file: unexpected DataError: variable_path {varfile_path} " 

430 # f"args {args}") 

431 raise e 2ibmbnbobEbubFbR e Y ; i m : n o p q r s t u = c v w x y z ? f A B @

432 for name, value in resulting_vars: 2a mbnbobEbFbK d R h j , S k / - . l g

433 self.set(name, value, varfile_path) 1aKdRhj,Sk/-.lg

434 

435 @staticmethod 1aI

436 def _get_prefix(value): 1aI

437 if utils.is_dict_like(value): 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l @bTbX

438 return '&' 2D jb| _ ebkb} C ` dbfbgbhblbd Y ; i m : n o p q r s t j u = c v w x y z ? f A B , k / - @ . l

439 elif utils.is_list_like(value): 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l @bTbX

440 return '@' 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l @bTbX

441 else: 

442 return '$' 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l @bTbX

443 

444 def __iter__(self): 1aI

445 for name, value in self._vars.store.data.items(): 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l @bTbX

446 source = self._sources[name] 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l @bTbX

447 prefix = self._get_prefix(value) 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l @bTbX

448 name = u'{0}{{{1}}}'.format(prefix, name) 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l @bTbX

449 if source == self.ARGUMENT_SOURCE: 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l @bTbX

450 yield ArgumentInfo(name, value) 2qbrbsbvbcbtbabY ; i m : n o p q r s t j u = c v w x y z ? A B , k - @ . l

451 else: 

452 yield VariableInfo(name, value, source) 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l @bTbX

453 

454 

455class DatafileRetriever(object): 1aI

456 def __init__(self, lib_cache, resource_factory, namespace): 1aI

457 self._namespace = namespace 2a NbAbBbwbxbCbybKbLbMbObPbQbc RbSbX

458 self._lib_cache = lib_cache 2a NbAbBbwbxbCbybKbLbMbObPbQbc RbSbX

459 self._resource_factory = resource_factory 2a NbAbBbwbxbCbybKbLbMbObPbQbc RbSbX

460 self.keyword_cache = ExpiringCache() 2a NbAbBbwbxbCbybKbLbMbObPbQbc RbSbX

461 self._default_kws = None 2a NbAbBbwbxbCbybKbLbMbObPbQbc RbSbX

462 

463 def get_all_cached_library_names(self): 1aI

464 return self._lib_cache.get_all_cached_library_names() 25c

465 

466 @property 1aI

467 def default_kws(self): 1aI

468 if self._default_kws is None: 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E kcR e h pbg

469 self._default_kws = self._lib_cache.get_default_keywords() 2a D C b { U bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T ~ G H F E kcg

470 return self._default_kws 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E kcR e h pbg

471 

472 def expire_cache(self): 1aI

473 self.keyword_cache = ExpiringCache() 2a Z J L M N O LcMcwbxbybUbU V W mcNcOcPc[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ P Q Vb~ G H F HbIbJbd ac

474 self._lib_cache.expire() 2a Z J L M N O LcMcwbxbybUbU V W mcNcOcPc[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ P Q Vb~ G H F HbIbJbd ac

475 

476 def get_keywords_from_several(self, datafiles): 1aI

477 kws = set() 2a kcR pb

478 kws.update(self.default_kws) 2a kcR pb

479 for df in datafiles: 2a kcR pb

480 kws.update(self.get_keywords_from(df, RetrieverContext())) 2a R pb

481 return kws 2a kcR pb

482 

483 def get_keywords_from(self, datafile, ctx): 1aI

484 self._get_vars_recursive(datafile, ctx) 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d cbabR e h pbi m n o p q r s t j u 0 c v w x y z f A B S k l g X

485 ctx.allow_going_through_resources_again() 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d cbabR e h pbi m n o p q r s t j u 0 c v w x y z f A B S k l g X

486 return sorted(set( 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d cbabR e h pbi m n o p q r s t j u 0 c v w x y z f A B S k l g X

487 self._get_datafile_keywords(datafile) + 

488 self._get_imported_resource_keywords(datafile, ctx) + 

489 self._get_imported_library_keywords(datafile, ctx))) 

490 

491 def is_library_import_ok(self, datafile, imp, ctx): 1aI

492 self._get_vars_recursive(datafile, ctx) 2ibmbnbobDbub

493 return bool(self._lib_kw_getter(imp, ctx)) 2ibmbnbobDbub

494 

495 def is_variables_import_ok(self, datafile, imp, ctx): 1aI

496 self._get_vars_recursive(datafile, ctx) 2EbFb

497 return self._import_vars(ctx, datafile, imp) 2EbFb

498 

499 @staticmethod 1aI

500 def _get_datafile_keywords(datafile): 1aI

501 if isinstance(datafile, robotapi.ResourceFile): 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d cbabR e h pbi m n o p q r s t j u 0 c v w x y z f A B S k l g X

502 return [ResourceUserKeywordInfo(kw) for kw in datafile.keywords if not kw.name.startswith('#')] 1aKTPQE

503 return [TestCaseUserKeywordInfo(kw) for kw in datafile.keywords if not kw.name.startswith('#')] 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d cbabR e h pbi m n o p q r s t j u 0 c v w x y z f A B S k l g X

504 

505 def _get_imported_library_keywords(self, datafile, ctx): 1aI

506 return self._collect_kws_from_imports(datafile, robotapi.Library, 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d cbabR e h pbi m n o p q r s t j u 0 c v w x y z f A B S k l g X

507 self._lib_kw_getter, ctx) 

508 

509 def _collect_kws_from_imports(self, datafile, instance_type, getter, ctx): 1aI

510 kws = [] 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d cbabR e h pbi m n o p q r s t j u 0 c v w x y z f A B S k l g X

511 for imp in self._collect_import_of_type(datafile, instance_type): 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d cbabR e h pbi m n o p q r s t j u 0 c v w x y z f A B S k l g X

512 kws.extend(getter(imp, ctx)) 2a J L M N O b U V W K T P Q G H F E d R e h pbi m n o p q r s t j u 0 c v w x y z f A B S k l g

513 return kws 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d cbabR e h pbi m n o p q r s t j u 0 c v w x y z f A B S k l g X

514 

515 def _lib_kw_getter(self, imp, ctx): 1aI

516 # update cur dir for recursive import 

517 self._namespace.update_cur_dir_global_var(imp.directory) 2a J L M N O b ibmbnbobDbubE d R e h i m n o p q r s t j u 0 c v w x y z f A B k l g

518 name = ctx.replace_variables(imp.name) 2a J L M N O b ibmbnbobDbubE d R e h i m n o p q r s t j u 0 c v w x y z f A B k l g

519 name = self._convert_to_absolute_path(name, imp) 2a J L M N O b ibmbnbobDbubE d R e h i m n o p q r s t j u 0 c v w x y z f A B k l g

520 args = [ctx.replace_variables(a) for a in imp.args] 2a J L M N O b ibmbnbobDbubE d R e h i m n o p q r s t j u 0 c v w x y z f A B k l g

521 alias = ctx.replace_variables(imp.alias) if imp.alias else None 2a J L M N O b ibmbnbobDbubE d R e h i m n o p q r s t j u 0 c v w x y z f A B k l g

522 return self._lib_cache.get_library_keywords(name, args, alias) 2a J L M N O b ibmbnbobDbubE d R e h i m n o p q r s t j u 0 c v w x y z f A B k l g

523 

524 @staticmethod 1aI

525 def _convert_to_absolute_path(name, import_): 1aI

526 full_name = os.path.join(import_.directory, name) 2a J L M N O b ibmbnbobDbubE d R e h i m n o p q r s t j u 0 c v w x y z f A B k l g

527 if os.path.exists(full_name): 2a J L M N O b ibmbnbobDbubE d R e h i m n o p q r s t j u 0 c v w x y z f A B k l g

528 return full_name 2M N O ibnbDbE R e i m n o p q r s t u 0 c v w x y z f A B

529 return name 2a J L b mbobubE d R e h i m n o p q r s t j u c v w x y z f A B k l g

530 

531 @staticmethod 1aI

532 def _collect_import_of_type(datafile, instance_type): 1aI

533 return [imp for imp in datafile.imports 2a D jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 { ibmbnbobEbDbubFbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d zbqbrbsbvbcbtbabR e h pbY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g GbX

534 if isinstance(imp, instance_type)] 

535 

536 def _get_imported_resource_keywords(self, datafile, ctx): 1aI

537 return self._collect_kws_from_imports(datafile, robotapi.Resource, 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d cbabR e h pbi m n o p q r s t j u 0 c v w x y z f A B S k l g X

538 self._res_kw_recursive_getter, 

539 ctx) 

540 

541 def _res_kw_recursive_getter(self, imp, ctx): 1aI

542 kws = [] 2a b U V W K T P Q G H F E d R e h pbi m n o p q r s t j u c v w x y z f A B S k l g

543 res = self._resource_factory.get_resource_from_import(imp, ctx) 2a b U V W K T P Q G H F E d R e h pbi m n o p q r s t j u c v w x y z f A B S k l g

544 if not res or res in ctx.parsed: 2a b U V W K T P Q G H F E d R e h pbi m n o p q r s t j u c v w x y z f A B S k l g

545 return kws 1abFEdRehimnopqrstjucvwxyzfABklg

546 ctx.parsed.add(res) 2a b U V W K T P Q G H F E d R e h pbi m n o p q r s t j u c v w x y z f A B S k l g

547 ctx.set_variables_from_datafile_variable_table(res) 2a b U V W K T P Q G H F E d R e h pbi m n o p q r s t j u c v w x y z f A B S k l g

548 for child in self._collect_import_of_type(res, robotapi.Resource): 2a b U V W K T P Q G H F E d R e h pbi m n o p q r s t j u c v w x y z f A B S k l g

549 kws.extend(self._res_kw_recursive_getter(child, ctx)) 2a b U V W T P Q G H F E d R e h pbi m n o p q r s t j u c v w x y z f A B k l g

550 kws.extend(self._get_imported_library_keywords(res, ctx)) 2a b U V W K T P Q G H F E d R e h pbi m n o p q r s t j u c v w x y z f A B S k l g

551 return [ResourceUserKeywordInfo(kw) for kw in res.keywords if not kw.name.startswith('#')] + kws 2a b U V W K T P Q G H F E d R e h pbi m n o p q r s t j u c v w x y z f A B S k l g

552 

553 def get_variables_from(self, datafile, ctx=None): 1aI

554 return self._get_vars_recursive(datafile, 2D jb| _ ebkb} C ` dbfbgbhblbb 2 d zbqbrbsbvbcbtbabY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l X

555 ctx or RetrieverContext()).vars 

556 

557 def _get_vars_recursive(self, datafile, ctx): 1aI

558 ctx.set_variables_from_datafile_variable_table(datafile) 2a D jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 { ibmbnbobEbDbubFbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d zbqbrbsbvbcbtbabR e h pbY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g X

559 self._collect_vars_from_variable_files(datafile, ctx) 2a D jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 { ibmbnbobEbDbubFbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d zbqbrbsbvbcbtbabR e h pbY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g X

560 self._collect_each_res_import(datafile, ctx, self._var_collector) 2a D jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 { ibmbnbobEbDbubFbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d zbqbrbsbvbcbtbabR e h pbY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g X

561 return ctx 2a D jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 { ibmbnbobEbDbubFbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d zbqbrbsbvbcbtbabR e h pbY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g X

562 

563 def _collect_vars_from_variable_files(self, datafile, ctx): 1aI

564 for imp in self._collect_import_of_type(datafile, robotapi.Variables): 2a D jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 { ibmbnbobEbDbubFbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d zbqbrbsbvbcbtbabR e h pbY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g X

565 self._import_vars(ctx, datafile, imp) 2a ibmbnbobEbubFbK d R e h Y ; i m : n o p q r s t j u = c v w x y z ? f A B , S k / - @ . l g

566 

567 @staticmethod 1aI

568 def _import_vars(ctx, datafile, imp): 1aI

569 varfile_path = os.path.abspath(os.path.join(datafile.directory, ctx.replace_variables(imp.name))) 2a ibmbnbobEbubFbK d R e h Y ; i m : n o p q r s t j u = c v w x y z ? f A B , S k / - @ . l g

570 args = [ctx.replace_variables(a) for a in imp.args] 2a ibmbnbobEbubFbK d R e h Y ; i m : n o p q r s t j u = c v w x y z ? f A B , S k / - @ . l g

571 try: 2a ibmbnbobEbubFbK d R e h Y ; i m : n o p q r s t j u = c v w x y z ? f A B , S k / - @ . l g

572 ctx.vars.set_from_file(varfile_path, args) 2a ibmbnbobEbubFbK d R e h Y ; i m : n o p q r s t j u = c v w x y z ? f A B , S k / - @ . l g

573 return True 2a mbnbobEbFbK d R h j , S k / - . l g

574 except (robotapi.DataError, Exception): 2ibmbnbobEbubFbR e Y ; i m : n o p q r s t u = c v w x y z ? f A B @

575 return False # DEBUG: log somewhere 2ibmbnbobEbubFbR e Y ; i m : n o p q r s t u = c v w x y z ? f A B @

576 

577 def _var_collector(self, res, ctx, items): 1aI

578 _ = items 2a b 2 ibU V W K T P Q G H F E d R e h pbY j c f , S k / - . l g

579 self._get_vars_recursive(res, ctx) 2a b 2 ibU V W K T P Q G H F E d R e h pbY j c f , S k / - . l g

580 

581 def get_keywords_cached(self, datafile, context_factory, caseless=False): 1aI

582 values = self.keyword_cache.get(datafile.source) 2a D jb!bZb[bZ | ,b_ eb0b1b2bbckbJ L M N O } C ` dbfbgbhblb3bb 2 { U V W bb#byc$bzcAc-b.b/b:bK ^b5b_b`b[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T %b'b(b)b9bBc*b]b+b;b=b?bP Q Vb~ G H F E e 8b7bcc6bh g

583 if not values: 2a D jb!bZb[bZ | ,b_ eb0b1b2bbckbJ L M N O } C ` dbfbgbhblb3bb 2 { U V W bb#byc$bzcAc-b.b/b:bK ^b5b_b`b[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T %b'b(b)b9bBc*b]b+b;b=b?bP Q Vb~ G H F E e 8b7bcc6bh g

584 words = self.get_keywords_from(datafile, context_factory.ctx_for_datafile(datafile)) 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E e h g

585 words.extend(self.default_kws) 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E e h g

586 values = _Keywords(words, caseless=caseless) 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E e h g

587 self.keyword_cache.put(datafile.source, values) 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E e h g

588 # print(f"DEBUG: namespace.py DatafileRetrieve get_keywords_cached returning cached keywords values=={values}" 

589 # f"\ndatafile={datafile.source}") 

590 # print(f"DEBUG: namespace.py DatafileRetrieve get_keywords_cached datafile = {datafile.source}") 

591 return values 2a D jb!bZb[bZ | ,b_ eb0b1b2bbckbJ L M N O } C ` dbfbgbhblb3bb 2 { U V W bb#byc$bzcAc-b.b/b:bK ^b5b_b`b[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T %b'b(b)b9bBc*b]b+b;b=b?bP Q Vb~ G H F E e 8b7bcc6bh g

592 

593 def _get_user_keywords_from(self, datafile): 1aI

594 return list(self._get_user_keywords_recursive(datafile, 

595 RetrieverContext())) 

596 

597 def _get_user_keywords_recursive(self, datafile, contxt): 1aI

598 kws = set() 

599 kws.update(datafile.keywords) 

600 kws_from_res = self._collect_each_res_import( 

601 datafile, contxt, 

602 lambda res, ctxt, kwords: 

603 kws.update(self._get_user_keywords_recursive(res, contxt))) 

604 kws.update(kws_from_res) 

605 return kws 

606 

607 def _collect_each_res_import(self, datafile, ctx, collector): 1aI

608 items = set() 2a D jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 { ibmbnbobEbDbubFbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d zbqbrbsbvbcbtbabR e h pbY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g GbX

609 ctx.set_variables_from_datafile_variable_table(datafile) 2a D jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 { ibmbnbobEbDbubFbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d zbqbrbsbvbcbtbabR e h pbY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g GbX

610 for imp in self._collect_import_of_type(datafile, robotapi.Resource): 2a D jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 { ibmbnbobEbDbubFbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d zbqbrbsbvbcbtbabR e h pbY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g GbX

611 res = self._resource_factory.get_resource_from_import(imp, ctx) 2a b 2 ibmbnbobEbubFbU V W K T P Q G H F E d R e h pbY ; i m : n o p q r s t j u = c v w x y z ? f A B , S k / - @ . l g Gb

612 if res and res not in ctx.parsed: 2a b 2 ibmbnbobEbubFbU V W K T P Q G H F E d R e h pbY ; i m : n o p q r s t j u = c v w x y z ? f A B , S k / - @ . l g Gb

613 ctx.parsed.add(res) 2a b 2 ibU V W K T P Q G H F E d R e h pbY j c f , S k / - . l g Gb

614 collector(res, ctx, items) 2a b 2 ibU V W K T P Q G H F E d R e h pbY j c f , S k / - . l g Gb

615 return items 2a D jbZ | _ ebkbJ L M N O } C ` dbfbgbhblbb 2 { ibmbnbobEbDbubFbU V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E d zbqbrbsbvbcbtbabR e h pbY ; i m : n o p q r s t j u = 0 c v w x y z ? f A B , S k / - @ . l g GbX

616 

617 def get_resources_from(self, datafile, language=None): 1aI

618 resources = list(self._get_resources_recursive(datafile, RetrieverContext(), language=language)) 2a Gb

619 resources.sort(key=operator.attrgetter('name')) 2a Gb

620 return resources # DEBUG 2a Gb

621 

622 def _get_resources_recursive(self, datafile, ctx, language=None): 1aI

623 # DEBUG: at this point it is not relevant the language, we would only need the header 

624 resources = set() 2a Gb

625 res = self._collect_each_res_import(datafile, ctx, self._add_resource) 2a Gb

626 resources.update(res) 2a Gb

627 for child in datafile.children: 2a Gb

628 resources.update(self._get_resources_recursive(child, ctx, language=language)) 

629 return resources 2a Gb

630 

631 def _add_resource(self, res, ctx, items): 1aI

632 items.add(res) 2a Gb

633 items.update(self._get_resources_recursive(res, ctx)) 2a Gb

634 

635 

636class _Keywords(object): 1aI

637 

638 new_lang = None 1aI

639 # Not Used? regexp = re.compile(r"\s*(given|when|then|and|but)\s*(.*)", re.IGNORECASE) 

640 

641 def __init__(self, keywords, caseless=True, new_lang=None): 1aI

642 if not self.new_lang: 642 ↛ 655line 642 didn't jump to line 655 because the condition on line 642 was always true2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

643 if not new_lang: 643 ↛ 654line 643 didn't jump to line 654 because the condition on line 643 was always true2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

644 new_lang = ['en'] 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

645 try: 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

646 set_lang = shared_memory.ShareableList(new_lang, name="language") 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

647 except FileExistsError: # Other instance created file 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

648 set_lang = shared_memory.ShareableList(name="language") 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

649 try: 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

650 self.new_lang = Language.from_name(set_lang[0].replace('_','-')) 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

651 except ValueError: 

652 self.new_lang = Language.from_name(new_lang[0]) 

653 else: 

654 self.new_lang = Language.from_name(new_lang[0]) 

655 self.normalized_bdd_prefixes = utils.normalize_pipe_list(list(self.new_lang.bdd_prefixes), spaces=False) 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

656 self.gherkin_prefix = re.compile(fr'^({self.normalized_bdd_prefixes}) (.*)', re.IGNORECASE) 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

657 self.keywords = robotapi.NormalizedDict(ignore=['_'], caseless=caseless) 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

658 self.embedded_keywords = {} 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

659 self._add_keywords(keywords) 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

660 

661 def _add_keywords(self, keywords): 1aI

662 for kw in keywords: 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

663 self._add_keyword(kw) 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

664 

665 def _add_keyword(self, kw): 1aI

666 # DEBUG: this hack creates a preference for local keywords over 

667 # resources and libraries Namespace should be rewritten to handle 

668 # keyword preference order 

669 if kw.name not in self.keywords: 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

670 self.keywords[kw.name] = kw 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

671 self._add_embedded(kw) 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

672 self.keywords[kw.longname] = kw 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

673 

674 def _add_embedded(self, kw): 1aI

675 if '$' not in kw.name: 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

676 return 2a D Z J L M N O C b { U V W bbK [ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q ~ G H F E Ybe h g

677 try: 2a b bb[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q e h g

678 handler = EmbeddedArgsHandler(kw) 2a b bb[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q e h g

679 self.embedded_keywords[handler.name_regexp] = kw 2a b bb[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q e h g

680 if hasattr(handler, 'longname_regexp'): 680 ↛ exitline 680 didn't return from function '_add_embedded' because the condition on line 680 was always true2a b bb[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q e h g

681 self.embedded_keywords[handler.longname_regexp] = kw 2a b bb[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T P Q e h g

682 # print(f"DEBUG: namespace.py _add_embedded add kw={kw.name} longname={kw.longname}\n" 

683 # f"handler.name_regexp={handler.name_regexp}") 

684 except TypeError: 

685 pass 

686 

687 def get(self, kw_name, origin=None): 1aI

688 if kw_name in self.keywords: 2a D jb!bZb[bZ | ,b_ eb0b1b2bbckbJ L M N O } C ` dbfbgbhblb3bb 2 { U V W bb#byc$bzcAc-b.b/b:bK ^b5b_b`b[ 7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 ] 6 ^ T %b'b(b)b9bBc*b]b+b;b=b?bP Q Vb~ G H F E ncocYbQc6clc7c8ce 8b7bcc6bh g

689 # filename = os.path.basename(origin.source) 

690 # print(f"DEBUG: namespace.py _Keywords get keywords in loop FOUND {kw_name} @ {filename}" 

691 # f" RETURNING {self.keywords[kw_name]} {self.keywords[kw_name].source == filename}") 

692 return self.keywords[kw_name] 2D jb!bZb[bZ | ,b_ eb0b1b2bbckbJ L M N O } C ` dbfbgbhblb3bb 2 { U V W bbyc$bzcAc[ 3 4 1 5 ] 6 ^ T %b'b(b)b9bBc*b]b+bP Q Vb~ G H F E YbQc6clc7c8ce 7bcc6bh g

693 # print(f"DEBUG: namespace.py _Keywords get keywords {self.keywords}") 

694 bdd_name = self._get_bdd_name(kw_name) 2a D jb!bZbZ | _ eb0b1b2bkbJ L M N O } C ` dbfbgbhblb3bb 2 { #b$b-b.b/b:bK ^b5b_b`b7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 6 T %b'b(b)b9b*b]b+b;b=b?bP Q VbG H F E ncocQclc8b7b6b

695 if bdd_name and bdd_name in self.keywords: 2a D jb!bZbZ | _ eb0b1b2bkbJ L M N O } C ` dbfbgbhblb3bb 2 { #b$b-b.b/b:bK ^b5b_b`b7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 6 T %b'b(b)b9b*b]b+b;b=b?bP Q VbG H F E ncocQclc8b7b6b

696 return self.keywords[bdd_name] 2Qc8b

697 # print(f"DEBUG: namespace.py _Keywords get embedded kws {self.embedded_keywords}" 

698 # f"\nseaching keyword={kw_name}") 

699 for regexp in self.embedded_keywords: 2a D jb!bZbZ | _ eb0b1b2bkbJ L M N O } C ` dbfbgbhblb3bb 2 { #b$b-b.b/b:bK ^b5b_b`b7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 6 T %b'b(b)b9b*b]b+b;b=b?bP Q VbG H F E ncoclc8b7b6b

700 try: 2a b 2 #b$b-b.b/b:b7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 6 T %b'b(b)b9b*b+b;b=b?bP Q Vbncoclc8b7b6b

701 if regexp.match(kw_name) or (bdd_name and regexp.match(bdd_name)): 2a b 2 #b$b-b.b/b:b7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 6 T %b'b(b)b9b*b+b;b=b?bP Q Vbncoclc8b7b6b

702 return self.embedded_keywords[regexp] 2b 2 nc

703 except AttributeError: 2ncoclc

704 pass 2ncoclc

705 return None 2a D jb!bZbZ | _ eb0b1b2bkbJ L M N O } C ` dbfbgbhblb3bb 2 { #b$b-b.b/b:bK ^b5b_b`b7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 6 T %b'b(b)b9b*b]b+b;b=b?bP Q VbG H F E oclc8b7b6b

706 

707 def _get_bdd_name(self, kw_name): 1aI

708 match = self.gherkin_prefix.match(kw_name) 2a D jb!bZbZ | _ eb0b1b2bkbJ L M N O } C ` dbfbgbhblb3bb 2 { #b$b-b.b/b:bK ^b5b_b`b7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 6 T %b'b(b)b9b*b]b+b;b=b?bP Q VbG H F E ncocQclc8b7b6b

709 # print(f"DEBUG: namespace.py _Keywords _get_bdd_name match={match}") 

710 return match.group(2) if match else None 2a D jb!bZbZ | _ eb0b1b2bkbJ L M N O } C ` dbfbgbhblb3bb 2 { #b$b-b.b/b:bK ^b5b_b`b7 8 9 3 ! # $ % ' ( 4 ) 1 * + 5 6 T %b'b(b)b9b*b]b+b;b=b?bP Q VbG H F E ncocQclc8b7b6b