Skip to content

Commit

Permalink
Minor cleanup/tuning.
Browse files Browse the repository at this point in the history
The motivaiton was trying to make finding keyword handlers a bit
faster to address #4659. Didn't seem to have any measurable effect,
but I consider this code better anyway.
  • Loading branch information
pekkaklarck authored and yanne committed Mar 17, 2023
1 parent 36230f3 commit 9594262
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 30 deletions.
17 changes: 8 additions & 9 deletions src/robot/libraries/BuiltIn.py
Original file line number Diff line number Diff line change
Expand Up @@ -1865,23 +1865,20 @@ def run_keyword(self, name, *args):
can be a variable and thus set dynamically, e.g. from a return value of
another keyword or from the command line.
"""
ctx = self._context
if (is_string(name)
and not ctx.dry_run
and not self._accepts_embedded_arguments(name)):
name, args = self._replace_variables_in_name([name] + list(args))
if not is_string(name):
raise RuntimeError('Keyword name must be a string.')
ctx = self._context
if not (ctx.dry_run or self._accepts_embedded_arguments(name, ctx)):
name, args = self._replace_variables_in_name([name] + list(args))
parent = ctx.steps[-1] if ctx.steps else (ctx.test or ctx.suite)
kw = Keyword(name, args=args, parent=parent,
lineno=getattr(parent, 'lineno', None))
return kw.run(ctx)

def _accepts_embedded_arguments(self, name):
def _accepts_embedded_arguments(self, name, ctx):
if '{' in name:
runner = self._context.get_runner(name)
if hasattr(runner, 'embedded_args'):
return True
runner = ctx.get_runner(name)
return runner and hasattr(runner, 'embedded_args')
return False

def _replace_variables_in_name(self, name_and_args):
Expand All @@ -1890,6 +1887,8 @@ def _replace_variables_in_name(self, name_and_args):
if not resolved:
raise DataError(f'Keyword name missing: Given arguments {name_and_args} '
f'resolved to an empty list.')
if not is_string(resolved[0]):
raise RuntimeError('Keyword name must be a string.')
return resolved[0], resolved[1:]

@run_keyword_variant(resolve=0, dry_run=True)
Expand Down
2 changes: 2 additions & 0 deletions src/robot/running/handlerstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ def __len__(self):
def __contains__(self, name):
if name in self._normal:
return True
if not self._embedded:
return False
return any(template.matches(name) for template in self._embedded)

def __getitem__(self, name):
Expand Down
36 changes: 15 additions & 21 deletions src/robot/running/namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,10 +311,8 @@ def _get_bdd_style_runner(self, name, prefixes):
return None

def _get_implicit_runner(self, name):
runner = self._get_runner_from_resource_files(name)
if not runner:
runner = self._get_runner_from_libraries(name)
return runner
return (self._get_runner_from_resource_files(name) or
self._get_runner_from_libraries(name))

def _get_runner_from_suite_file(self, name):
if name not in self.user_keywords.handlers:
Expand Down Expand Up @@ -377,8 +375,8 @@ def _get_runner_from_resource_files(self, name):
handlers = self._select_best_matches(handlers)
if len(handlers) > 1:
handlers = self._filter_based_on_search_order(handlers)
if len(handlers) != 1:
self._raise_multiple_keywords_found(handlers, name)
if len(handlers) > 1:
self._raise_multiple_keywords_found(handlers, name)
return handlers[0].create_runner(name, self.languages)

def _get_runner_from_libraries(self, name):
Expand All @@ -393,8 +391,8 @@ def _get_runner_from_libraries(self, name):
handlers = self._filter_based_on_search_order(handlers)
if len(handlers) > 1:
handlers, pre_run_message = self._filter_stdlib_handler(handlers)
if len(handlers) != 1:
self._raise_multiple_keywords_found(handlers, name)
if len(handlers) > 1:
self._raise_multiple_keywords_found(handlers, name)
runner = handlers[0].create_runner(name, self.languages)
if pre_run_message:
runner.pre_run_messages += (pre_run_message,)
Expand Down Expand Up @@ -447,11 +445,12 @@ def _custom_and_standard_keyword_conflict_warning(self, custom, standard):
)

def _get_explicit_runner(self, name):
handlers_and_names = [
(handler, kw_name)
for owner_name, kw_name in self._yield_owner_and_kw_names(name)
for handler in self._yield_handlers(owner_name, kw_name)
]
handlers_and_names = []
for owner_name, kw_name in self._get_owner_and_kw_names(name):
for owner in chain(self.libraries.values(), self.resources.values()):
if eq(owner.name, owner_name) and kw_name in owner.handlers:
for handler in owner.handlers.get_handlers(kw_name):
handlers_and_names.append((handler, kw_name))
if not handlers_and_names:
return None
if len(handlers_and_names) == 1:
Expand All @@ -464,15 +463,10 @@ def _get_explicit_runner(self, name):
handler, kw_name = handlers_and_names[handlers.index(matches[0])]
return handler.create_runner(kw_name, self.languages)

def _yield_owner_and_kw_names(self, full_name):
def _get_owner_and_kw_names(self, full_name):
tokens = full_name.split('.')
for i in range(1, len(tokens)):
yield '.'.join(tokens[:i]), '.'.join(tokens[i:])

def _yield_handlers(self, owner_name, name):
for owner in chain(self.libraries.values(), self.resources.values()):
if eq(owner.name, owner_name) and name in owner.handlers:
yield from owner.handlers.get_handlers(name)
return [('.'.join(tokens[:index]), '.'.join(tokens[index:]))
for index in range(1, len(tokens))]

def _raise_multiple_keywords_found(self, handlers, name, implicit=True):
if any(hand.supports_embedded_args for hand in handlers):
Expand Down

0 comments on commit 9594262

Please sign in to comment.