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
« 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.
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
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
35class Namespace(object): 1aI
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
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
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
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
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
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
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
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
109 def resource_filename_changed(self, old_name, new_name): 1aI
110 self._resource_factory.resource_filename_changed(old_name, new_name) 2a AbBbwbxbCbyb
112 def reset_resource_and_library_cache(self): 1aI
113 self._init_caches() 2a NbAbBbwbxbCbybKbLbMbObPbQbc RbSb
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
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
122 def clear_update_listeners(self): 1aI
123 self._update_listeners.clear() # = list() # DEBUG .clear()
125 def register_content_assist_hook(self, hook): 1aI
126 self._content_assist_hooks.append(hook) 1X
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
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
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
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
170 def get_all_cached_library_names(self): 1aI
171 return self._retriever.get_all_cached_library_names() 25c
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
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] == '$'
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
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
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
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))
221 def get_resources(self, datafile, language=None): 1aI
222 return self._retriever.get_resources_from(datafile, language=language) 2a Gb
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)
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
233 def new_resource(self, path, directory=''): 1aI
234 return self._resource_factory.new_resource(directory, path) 2{c|cMbG H F HbIbJb
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
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
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
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))
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))
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
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
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
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
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
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
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
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
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
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
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
314 def allow_going_through_resources_again(self): 1aI
315 """Resets the parsed resources cache.
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
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 }
364 ARGUMENT_SOURCE = object() 1aI
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
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
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
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
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)
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
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
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
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
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
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
463 def get_all_cached_library_names(self): 1aI
464 return self._lib_cache.get_all_cached_library_names() 25c
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
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
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
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)))
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
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
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
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)
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
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
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
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)]
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)
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
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
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
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
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 @
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
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
593 def _get_user_keywords_from(self, datafile): 1aI
594 return list(self._get_user_keywords_recursive(datafile,
595 RetrieverContext()))
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
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
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
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
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
636class _Keywords(object): 1aI
638 new_lang = None 1aI
639 # Not Used? regexp = re.compile(r"\s*(given|when|then|and|but)\s*(.*)", re.IGNORECASE)
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
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
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
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
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
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