Skip to content

Commit

Permalink
Support for RF 7.2 GROUP syntax (#733)
Browse files Browse the repository at this point in the history
  • Loading branch information
bhirsz authored Jan 2, 2025
1 parent 3bf2f4d commit b94494b
Show file tree
Hide file tree
Showing 48 changed files with 645 additions and 73 deletions.
4 changes: 3 additions & 1 deletion robotidy/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Methods for transforming Robot Framework ast model programmatically.
"""

from __future__ import annotations

from pathlib import Path
Expand Down Expand Up @@ -37,7 +38,8 @@ def transform_model(model, root_dir: str, output: str | None = None, **kwargs) -
"""
robotidy_class = get_robotidy(root_dir, output, **kwargs)
disabler_finder = disablers.RegisterDisablers(
robotidy_class.config.formatting.start_line, robotidy_class.config.formatting.end_line
robotidy_class.config.formatting.start_line,
robotidy_class.config.formatting.end_line,
)
disabler_finder.visit(model)
if disabler_finder.is_disabled_in_file(disablers.ALL_TRANSFORMERS):
Expand Down
12 changes: 10 additions & 2 deletions robotidy/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ def transform_files(self):
self.output_diff(model_path, old_model, new_model)
changed_files += 1
except DataError as err:
click.echo(f"Failed to decode {source} with an error: {err}\nSkipping file", err=True)
click.echo(
f"Failed to decode {source} with an error: {err}\nSkipping file",
err=True,
)
changed_files = previous_changed_files
skipped_files += 1
return self.formatting_result(all_files, changed_files, skipped_files, stdin)
Expand Down Expand Up @@ -141,7 +144,12 @@ def get_line_ending(self, path: str):
return f.newlines[0]
return self.config.formatting.line_sep

def output_diff(self, path: str, old_model: misc.StatementLinesCollector, new_model: misc.StatementLinesCollector):
def output_diff(
self,
path: str,
old_model: misc.StatementLinesCollector,
new_model: misc.StatementLinesCollector,
):
if not self.config.show_diff:
return
old = [l + "\n" for l in old_model.text.splitlines()]
Expand Down
23 changes: 19 additions & 4 deletions robotidy/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@
"--endline",
],
},
{"name": "File exclusion", "options": ["--exclude", "--extend-exclude", "--skip-gitignore"]},
{
"name": "File exclusion",
"options": ["--exclude", "--extend-exclude", "--skip-gitignore"],
},
skip.option_group,
{
"name": "Other",
Expand Down Expand Up @@ -124,7 +127,11 @@ def print_transformer_docs(transformer):
@decorators.optional_rich
def print_description(name: str, target_version: int):
# TODO: --desc works only for default transformers, it should also print custom transformer desc
transformers = load_transformers(TransformConfigMap([], [], []), allow_disabled=True, target_version=target_version)
transformers = load_transformers(
TransformConfigMap([], [], []),
allow_disabled=True,
target_version=target_version,
)
transformer_by_names = {transformer.name: transformer for transformer in transformers}
if name == "all":
for transformer in transformers:
Expand Down Expand Up @@ -159,7 +166,11 @@ def print_transformers_list(global_config: config_module.MainConfig):
table = Table(title="Transformers", header_style="bold red")
table.add_column("Name", justify="left", no_wrap=True)
table.add_column("Enabled")
transformers = load_transformers(TransformConfigMap([], [], []), allow_disabled=True, target_version=target_version)
transformers = load_transformers(
TransformConfigMap([], [], []),
allow_disabled=True,
target_version=target_version,
)
transformers.extend(_load_external_transformers(transformers, config.transformers_config, target_version))

for transformer in transformers:
Expand Down Expand Up @@ -194,7 +205,11 @@ def generate_config(global_config: config_module.MainConfig):
raise exceptions.MissingOptionalTomliWDependencyError()
target_version = global_config.default.target_version
config = global_config.default_loaded
transformers = load_transformers(TransformConfigMap([], [], []), allow_disabled=True, target_version=target_version)
transformers = load_transformers(
TransformConfigMap([], [], []),
allow_disabled=True,
target_version=target_version,
)
transformers.extend(_load_external_transformers(transformers, config.transformers_config, target_version))

toml_config = {
Expand Down
22 changes: 18 additions & 4 deletions robotidy/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,12 @@ def convert_transformers_config(
is_config: bool = False,
) -> list[TransformConfig]:
return [
TransformConfig(tr, force_include=force_included, custom_transformer=custom_transformer, is_config=is_config)
TransformConfig(
tr,
force_include=force_included,
custom_transformer=custom_transformer,
is_config=is_config,
)
for tr in config.get(param_name, ())
]

Expand Down Expand Up @@ -186,7 +191,10 @@ def from_config_file(self, config: dict, config_path: Path) -> "RawConfig":
Dictionary key:values needs to be normalized and parsed to correct types.
"""
options_map = map_class_fields_with_their_types(self)
parsed_config = {"defined_in_config": {"defined_in_config", "config_path"}, "config_path": config_path}
parsed_config = {
"defined_in_config": {"defined_in_config", "config_path"},
"config_path": config_path,
}
for key, value in config.items():
# workaround to be able to use two option names for same action - backward compatibility change
if key == "load_transformers":
Expand All @@ -206,7 +214,10 @@ def from_config_file(self, config: dict, config_path: Path) -> "RawConfig":
parsed_config[key] = [convert_transform_config(val, key) for val in value]
elif key == "src":
parsed_config[key] = tuple(value)
elif value_type in ("Pattern", Pattern): # future typing for 3.8 provides type as str
elif value_type in (
"Pattern",
Pattern,
): # future typing for 3.8 provides type as str
parsed_config[key] = misc.validate_regex(value)
else:
parsed_config[key] = value
Expand Down Expand Up @@ -273,7 +284,10 @@ def get_sources(self, sources: tuple[str, ...]) -> tuple[str, ...] | None:

def get_sources_with_configs(self):
sources = files.get_paths(
self.sources, self.default.exclude, self.default.extend_exclude, self.default.skip_gitignore
self.sources,
self.default.exclude,
self.default.extend_exclude,
self.default.skip_gitignore,
)
for source in sources:
if self.default.config:
Expand Down
7 changes: 6 additions & 1 deletion robotidy/disablers.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,12 @@ def is_line_start(node):


class DisablersInFile:
def __init__(self, start_line: Optional[int], end_line: Optional[int], file_end: Optional[int] = None):
def __init__(
self,
start_line: Optional[int],
end_line: Optional[int],
file_end: Optional[int] = None,
):
self.start_line = start_line
self.end_line = end_line
self.file_end = file_end
Expand Down
7 changes: 6 additions & 1 deletion robotidy/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,12 @@ def get_path_relative_to_project_root(path: Path, root_parent: Path) -> Path:
return path


def get_paths(src: tuple[str, ...], exclude: Pattern | None, extend_exclude: Pattern | None, skip_gitignore: bool):
def get_paths(
src: tuple[str, ...],
exclude: Pattern | None,
extend_exclude: Pattern | None,
skip_gitignore: bool,
):
root = find_project_root(src)
if skip_gitignore:
gitignore = None
Expand Down
16 changes: 14 additions & 2 deletions robotidy/skip.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,16 @@ def __init__(self, skip_config: SkipConfig):

@staticmethod
def parse_skip_settings(skip_config):
settings = {"settings", "arguments", "setup", "teardown", "timeout", "template", "return_statement", "tags"}
settings = {
"settings",
"arguments",
"setup",
"teardown",
"timeout",
"template",
"return_statement",
"tags",
}
skip_settings = set()
for setting in settings:
if getattr(skip_config, setting):
Expand Down Expand Up @@ -156,7 +165,10 @@ def section(self, name):
documentation_option = click.option("--skip-documentation", is_flag=True, help="Skip formatting of documentation")
return_values_option = click.option("--skip-return-values", is_flag=True, help="Skip formatting of return values")
keyword_call_option = click.option(
"--skip-keyword-call", type=str, multiple=True, help="Keyword call name that should not be formatted"
"--skip-keyword-call",
type=str,
multiple=True,
help="Keyword call name that should not be formatted",
)
keyword_call_pattern_option = click.option(
"--skip-keyword-call-pattern",
Expand Down
8 changes: 7 additions & 1 deletion robotidy/transformers/AlignSettingsSection.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,13 @@ def align_rows(self, statements, look_up):
def calc_separator(self, index, up_to, indent_arg, token, look_up):
if index < up_to:
if self.fixed_width:
return max(self.fixed_width - len(token.value), self.formatting_config.space_count) * " "
return (
max(
self.fixed_width - len(token.value),
self.formatting_config.space_count,
)
* " "
)
arg_indent = self.argument_indent if indent_arg else 0
if indent_arg and index != 0:
return (
Expand Down
8 changes: 7 additions & 1 deletion robotidy/transformers/AlignTemplatedTestCases.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,13 @@ def align_header(self, statement):
for index, token in enumerate(statement.data_tokens[:-1]):
tokens.append(token)
if self.min_width:
separator = max(self.formatting_config.space_count, self.min_width - len(token.value)) * " "
separator = (
max(
self.formatting_config.space_count,
self.min_width - len(token.value),
)
* " "
)
else:
separator = (self.widths[index] - len(token.value) + self.formatting_config.space_count) * " "
tokens.append(Token(Token.SEPARATOR, separator))
Expand Down
16 changes: 14 additions & 2 deletions robotidy/transformers/AlignVariablesSection.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,13 @@ class AlignVariablesSection(Transformer):
To align all columns set ``up_to_column`` to 0.
"""

def __init__(self, up_to_column: int = 2, skip_types: str = "", min_width: int = None, fixed_width: int = None):
def __init__(
self,
up_to_column: int = 2,
skip_types: str = "",
min_width: int = None,
fixed_width: int = None,
):
super().__init__()
self.up_to_column = up_to_column - 1
self.min_width = min_width
Expand Down Expand Up @@ -121,7 +127,13 @@ def align_rows(self, statements, look_up):
def get_separator(self, index: int, up_to: int, token, look_up: dict[int, int]) -> str:
if index < up_to:
if self.fixed_width:
return max(self.fixed_width - len(token.value), self.formatting_config.space_count) * " "
return (
max(
self.fixed_width - len(token.value),
self.formatting_config.space_count,
)
* " "
)
return (look_up[index] - len(token.value)) * " "
else:
return self.formatting_config.separator
Expand Down
19 changes: 16 additions & 3 deletions robotidy/transformers/GenerateDocumentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,12 @@ class GenerateDocumentation(Transformer):

WHITESPACE_PATTERN = re.compile(r"(\s{2,}|\t)", re.UNICODE)

def __init__(self, overwrite: bool = False, doc_template: str = "google", template_directory: str | None = None):
def __init__(
self,
overwrite: bool = False,
doc_template: str = "google",
template_directory: str | None = None,
):
self.overwrite = overwrite
self.doc_template = self.load_template(doc_template, template_directory)
self.args_returns_finder = ArgumentsAndReturnsVisitor()
Expand Down Expand Up @@ -174,7 +179,11 @@ def visit_Keyword(self, node): # noqa
if not self.overwrite and self.args_returns_finder.doc_exists:
return node
formatting = FormattingData(self.formatting_config.continuation_indent, self.formatting_config.separator)
kw_data = KeywordData(node.name, self.args_returns_finder.arguments, self.args_returns_finder.returns)
kw_data = KeywordData(
node.name,
self.args_returns_finder.arguments,
self.args_returns_finder.returns,
)
generated = self.doc_template.render(keyword=kw_data, formatting=formatting)
doc_node = self.create_documentation_from_string(generated)
if self.overwrite:
Expand All @@ -186,7 +195,11 @@ def visit_Documentation(self, node): # noqa
return None

def create_documentation_from_string(self, doc_string):
new_line = [Token(Token.EOL), Token(Token.SEPARATOR, self.formatting_config.indent), Token(Token.CONTINUATION)]
new_line = [
Token(Token.EOL),
Token(Token.SEPARATOR, self.formatting_config.indent),
Token(Token.CONTINUATION),
]
tokens = [
Token(Token.SEPARATOR, self.formatting_config.indent),
Token(Token.DOCUMENTATION, "[Documentation]"),
Expand Down
13 changes: 11 additions & 2 deletions robotidy/transformers/IndentNestedKeywords.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,11 @@ def visit_SuiteSetup(self, node): # noqa
comments = misc.collect_comments_from_tokens(node.tokens, indent=None)
separator = self.get_separator()
new_line = misc.get_new_line()
tokens = [node.data_tokens[0], separator, *misc.join_tokens_with_token(lines[0][1], separator)]
tokens = [
node.data_tokens[0],
separator,
*misc.join_tokens_with_token(lines[0][1], separator),
]
formatted_tokens = self.parse_keyword_lines(lines, tokens, new_line, eol=node.tokens[-1])
if self.node_was_transformed(node.tokens, formatted_tokens):
node.tokens = formatted_tokens
Expand All @@ -144,7 +148,12 @@ def visit_Setup(self, node): # noqa
indent = node.tokens[0]
separator = self.get_separator()
new_line = misc.get_new_line(indent)
tokens = [indent, node.data_tokens[0], separator, *misc.join_tokens_with_token(lines[0][1], separator)]
tokens = [
indent,
node.data_tokens[0],
separator,
*misc.join_tokens_with_token(lines[0][1], separator),
]
comment = misc.merge_comments_into_one(node.tokens)
if comment:
# need to add comments on first line for [Setup] / [Teardown] settings
Expand Down
19 changes: 15 additions & 4 deletions robotidy/transformers/InlineIf.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,11 @@ def inline_if_from_branch(self, node, indent):
# check for ElseIfHeader first since it's child of IfHeader class
if isinstance(node.header, ElseIfHeader):
header = ElseIfHeader(
[Token(Token.ELSE_IF), Token(Token.SEPARATOR, separator), Token(Token.ARGUMENT, node.header.condition)]
[
Token(Token.ELSE_IF),
Token(Token.SEPARATOR, separator),
Token(Token.ARGUMENT, node.header.condition),
]
)
elif isinstance(node.header, IfHeader):
tokens = [Token(Token.SEPARATOR, indent)]
Expand All @@ -202,7 +206,10 @@ def inline_if_from_branch(self, node, indent):

@staticmethod
def to_inline_keyword(keyword, separator, last_token):
tokens = [Token(Token.SEPARATOR, separator), Token(Token.KEYWORD, keyword.keyword)]
tokens = [
Token(Token.SEPARATOR, separator),
Token(Token.KEYWORD, keyword.keyword),
]
for arg in keyword.get_tokens(Token.ARGUMENT):
tokens.extend([Token(Token.SEPARATOR, separator), arg])
tokens.append(last_token)
Expand Down Expand Up @@ -321,11 +328,15 @@ def handle_inline_if_create(self, node, indent, assign):
else_found = False
if isinstance(node.header, InlineIfHeader):
header = IfHeader.from_params(
condition=node.condition, indent=indent, separator=self.formatting_config.separator
condition=node.condition,
indent=indent,
separator=self.formatting_config.separator,
)
elif isinstance(node.header, ElseIfHeader):
header = ElseIfHeader.from_params(
condition=node.condition, indent=indent, separator=self.formatting_config.separator
condition=node.condition,
indent=indent,
separator=self.formatting_config.separator,
)
else:
header = ElseHeader.from_params(indent=indent)
Expand Down
5 changes: 4 additions & 1 deletion robotidy/transformers/NormalizeAssignments.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ class NormalizeAssignments(Transformer):
HANDLES_SKIP = frozenset({"skip_sections"})

def __init__(
self, equal_sign_type: str = "autodetect", equal_sign_type_variables: str = "remove", skip: Skip = None
self,
equal_sign_type: str = "autodetect",
equal_sign_type_variables: str = "remove",
skip: Skip = None,
):
super().__init__(skip)
self.remove_equal_sign = re.compile(r"\s?=$")
Expand Down
2 changes: 1 addition & 1 deletion robotidy/transformers/NormalizeNewLines.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def visit_If(self, node): # noqa
self.trim_empty_lines(node)
return self.generic_visit(node)

visit_For = visit_While = visit_Try = visit_If
visit_For = visit_While = visit_Group = visit_Try = visit_If

def visit_Statement(self, node): # noqa
tokens = []
Expand Down
Loading

0 comments on commit b94494b

Please sign in to comment.