Skip to content

Commit 9d44048

Browse files
adrszadadrianszadkowskibhirsz
authored
Add NormalizeTags transformer (#213)
* Add NormalizeTags transformer * fix line endings * Resolve PR comments, add option to only remove duplicates * rename parameter, resolve PR comments * Use classes, handle comments Co-authored-by: Adrian Szadkowski <adrian.szadkowski@zebra.com> Co-authored-by: Bartłomiej Hirsz <bartek.hirsz@gmail.com>
1 parent d1677d2 commit 9d44048

File tree

11 files changed

+412
-0
lines changed

11 files changed

+412
-0
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
.. _NormalizeTags:
2+
3+
NormalizeTags
4+
================================
5+
6+
NormalizeTags is not included in default transformers, that's why you need to call it with ``--transform`` explicitly::
7+
8+
robotidy --transform NormalizeTags src
9+
10+
Or configure `enable` parameter::
11+
12+
robotidy --configure NormalizeTags:enabled=True
13+
14+
15+
Supported cases: lowercase (default), uppercase, titlecase.
16+
You can configure case using `case` parameter::
17+
18+
robotidy --transform NormalizeTags:case=uppercase
19+
20+
21+
You can remove duplicates without normalizing case by setting normalize_case parameter to False::
22+
23+
robotidy --transform NormalizeTags:normalize_case=False
24+
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from robot.api.parsing import ModelTransformer, Tags, Token, DefaultTags, ForceTags
2+
import click
3+
4+
class NormalizeTags(ModelTransformer):
5+
"""
6+
Normalize tag names by normalizing case and removing duplicates.
7+
example usage:
8+
9+
robotidy --transform NormalizeTags:case=lowercase test.robot
10+
11+
Other supported cases: uppercase, titlecase. The default is lowercase.
12+
13+
You can also run it to remove duplicates but preserve current case by setting ``normalize_case`` parameter to False:
14+
15+
robotidy --transform NormalizeTags:normalize_case=False test.robot
16+
17+
See https://robotidy.readthedocs.io/en/latest/transformers/NormalizeTags.html for more examples.
18+
"""
19+
CASE_FUNCTIONS = {'lowercase': str.lower, 'uppercase': str.upper, 'titlecase': str.title}
20+
21+
def __init__(self, case: str = 'lowercase', normalize_case: bool = True):
22+
self.case = case.lower()
23+
self.normalize_case = normalize_case
24+
try:
25+
self.case_function = self.CASE_FUNCTIONS[self.case]
26+
except KeyError:
27+
raise click.BadOptionUsage(
28+
option_name='transform',
29+
message=f"Invalid configurable value: '{case}' for case for NormalizeTags transformer. "
30+
f"Supported cases: lowercase, uppercase, titlecase.\n")
31+
32+
def visit_Tags(self, node):
33+
return self.normalize_tags(node, Tags, indent=True)
34+
35+
def visit_DefaultTags(self, node):
36+
return self.normalize_tags(node, DefaultTags)
37+
38+
def visit_ForceTags(self, node):
39+
return self.normalize_tags(node, ForceTags)
40+
41+
def normalize_tags(self, node, tag_class, indent=False):
42+
tags = [tag.value for tag in node.data_tokens[1:]]
43+
if self.normalize_case:
44+
tags = self.convert_case(tags)
45+
tags = self.remove_duplicates(tags)
46+
comments = node.get_tokens(Token.COMMENT)
47+
if indent:
48+
tag_node = tag_class.from_params(tags, indent=self.formatting_config.separator,
49+
separator=self.formatting_config.separator)
50+
else:
51+
tag_node = tag_class.from_params(tags, separator=self.formatting_config.separator)
52+
if comments:
53+
tag_node.tokens = tag_node.tokens[:-1] + tuple(self.join_tokens(comments)) + (tag_node.tokens[-1],)
54+
return tag_node
55+
56+
def convert_case(self, tags):
57+
return [self.case_function(item) for item in tags]
58+
59+
def remove_duplicates(self, tags):
60+
return list(dict.fromkeys(tags))
61+
62+
def join_tokens(self, tokens):
63+
joined_tokens = []
64+
for token in tokens:
65+
joined_tokens.append(Token(Token.SEPARATOR, self.formatting_config.separator))
66+
joined_tokens.append(token)
67+
return joined_tokens
68+

robotidy/transformers/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
'NormalizeAssignments',
2525
'OrderSettings',
2626
'OrderSettingsSection',
27+
'NormalizeTags',
2728
'OrderTags',
2829
'AlignSettingsSection',
2930
'AlignVariablesSection',

tests/atest/transformers/NormalizeTags/__init__.py

Whitespace-only changes.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
*** Settings ***
2+
Documentation OrderTags acceptance tests
3+
Force Tags Tag1 tag1 tag2 tag3 tag4
4+
Default Tags Tag1 tag1 tag2 tag3 tag4
5+
6+
*** Test Cases ***
7+
No tags
8+
Keyword no tags
9+
10+
Different cases
11+
[Tags] Tag1 tag1 TAG1 other_tag
12+
Keyword different cases
13+
14+
Same cases
15+
[Tags] tag2 other_tag
16+
Keyword same cases
17+
18+
Not duplicates
19+
[Tags] tag3 tag4
20+
Keyword not duplicates
21+
22+
One Tag
23+
[Tags] tag5
24+
One Tag Keyword
25+
26+
*** Keywords ***
27+
Keyword no tags
28+
No Operation
29+
30+
Keyword same cases
31+
[Tags] tag2 other_tag
32+
No Operation
33+
34+
Keyword different cases
35+
[Tags] Tag1 tag1 TAG1 other_tag
36+
No Operation
37+
38+
Keyword not duplicates
39+
[Tags] tag3 tag4
40+
No Operation
41+
42+
One Tag Keyword
43+
[Tags] tag5
44+
No Operation
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
*** Settings ***
2+
Documentation OrderTags acceptance tests
3+
Force Tags tag1 tag2 tag3 tag4 tag5 # comment
4+
Default Tags tag1 tag2 tag3 tag4 tag5 # comment
5+
6+
*** Test Cases ***
7+
No tags
8+
Keyword no tags
9+
10+
Normalize case
11+
[Tags] foo_bar_baz_a foo_bar_baz_b foo_bar_baz_c foobarbazd foobarbaze foobarbazf foo bar baz g foo bar baz h foo bar baz i
12+
Keyword normalize case
13+
14+
Deduplicate
15+
[Tags] tag_a tag_b tag_c
16+
Keyword deduplicate
17+
18+
Deduplicate and normalize case
19+
[Tags] foo_bar_baz_a foo_bar_baz_b foo_bar_baz_c foobarbazd foobarbaze foobarbazf foo bar baz g foo bar baz h foo bar baz i
20+
Keyword deduplicate and normalize case
21+
22+
One Tag
23+
[Tags] one_tag_various cases
24+
One Tag Keyword
25+
26+
Multiline tags
27+
[Tags] tag1 tag2 tag3 tag4 tag5 # comment1 # comment2
28+
29+
*** Keywords ***
30+
Keyword no tags
31+
No Operation
32+
33+
Keyword normalize case
34+
[Tags] foo_bar_baz_a foo_bar_baz_b foo_bar_baz_c foobarbazd foobarbaze foobarbazf foo bar baz g foo bar baz h foo bar baz i
35+
No Operation
36+
37+
Keyword deduplicate
38+
[Tags] tag_a tag_b tag_c # comment
39+
No Operation
40+
41+
Keyword deduplicate and normalize case
42+
[Tags] foo_bar_baz_a foo_bar_baz_b foo_bar_baz_c foobarbazd foobarbaze foobarbazf foo bar baz g foo bar baz h foo bar baz i
43+
No Operation
44+
45+
One Tag Keyword
46+
[Tags] one_tag_various cases
47+
No Operation
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
*** Settings ***
2+
Documentation OrderTags acceptance tests
3+
Force Tags Tag1 Tag2 Tag3 Tag4 Tag5 # comment
4+
Default Tags Tag1 Tag2 Tag3 Tag4 Tag5 # comment
5+
6+
*** Test Cases ***
7+
No tags
8+
Keyword no tags
9+
10+
Normalize case
11+
[Tags] Foo_Bar_Baz_A Foo_Bar_Baz_B Foo_Bar_Baz_C Foobarbazd Foobarbaze Foobarbazf Foo Bar Baz G Foo Bar Baz H Foo Bar Baz I
12+
Keyword normalize case
13+
14+
Deduplicate
15+
[Tags] Tag_A Tag_B Tag_C
16+
Keyword deduplicate
17+
18+
Deduplicate and normalize case
19+
[Tags] Foo_Bar_Baz_A Foo_Bar_Baz_B Foo_Bar_Baz_C Foobarbazd Foobarbaze Foobarbazf Foo Bar Baz G Foo Bar Baz H Foo Bar Baz I
20+
Keyword deduplicate and normalize case
21+
22+
One Tag
23+
[Tags] One_Tag_Various Cases
24+
One Tag Keyword
25+
26+
Multiline tags
27+
[Tags] Tag1 Tag2 Tag3 Tag4 Tag5 # comment1 # comment2
28+
29+
*** Keywords ***
30+
Keyword no tags
31+
No Operation
32+
33+
Keyword normalize case
34+
[Tags] Foo_Bar_Baz_A Foo_Bar_Baz_B Foo_Bar_Baz_C Foobarbazd Foobarbaze Foobarbazf Foo Bar Baz G Foo Bar Baz H Foo Bar Baz I
35+
No Operation
36+
37+
Keyword deduplicate
38+
[Tags] Tag_A Tag_B Tag_C # comment
39+
No Operation
40+
41+
Keyword deduplicate and normalize case
42+
[Tags] Foo_Bar_Baz_A Foo_Bar_Baz_B Foo_Bar_Baz_C Foobarbazd Foobarbaze Foobarbazf Foo Bar Baz G Foo Bar Baz H Foo Bar Baz I
43+
No Operation
44+
45+
One Tag Keyword
46+
[Tags] One_Tag_Various Cases
47+
No Operation
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
*** Settings ***
2+
Documentation OrderTags acceptance tests
3+
Force Tags TAG1 TAG2 TAG3 TAG4 TAG5 # comment
4+
Default Tags TAG1 TAG2 TAG3 TAG4 TAG5 # comment
5+
6+
*** Test Cases ***
7+
No tags
8+
Keyword no tags
9+
10+
Normalize case
11+
[Tags] FOO_BAR_BAZ_A FOO_BAR_BAZ_B FOO_BAR_BAZ_C FOOBARBAZD FOOBARBAZE FOOBARBAZF FOO BAR BAZ G FOO BAR BAZ H FOO BAR BAZ I
12+
Keyword normalize case
13+
14+
Deduplicate
15+
[Tags] TAG_A TAG_B TAG_C
16+
Keyword deduplicate
17+
18+
Deduplicate and normalize case
19+
[Tags] FOO_BAR_BAZ_A FOO_BAR_BAZ_B FOO_BAR_BAZ_C FOOBARBAZD FOOBARBAZE FOOBARBAZF FOO BAR BAZ G FOO BAR BAZ H FOO BAR BAZ I
20+
Keyword deduplicate and normalize case
21+
22+
One Tag
23+
[Tags] ONE_TAG_VARIOUS CASES
24+
One Tag Keyword
25+
26+
Multiline tags
27+
[Tags] TAG1 TAG2 TAG3 TAG4 TAG5 # comment1 # comment2
28+
29+
*** Keywords ***
30+
Keyword no tags
31+
No Operation
32+
33+
Keyword normalize case
34+
[Tags] FOO_BAR_BAZ_A FOO_BAR_BAZ_B FOO_BAR_BAZ_C FOOBARBAZD FOOBARBAZE FOOBARBAZF FOO BAR BAZ G FOO BAR BAZ H FOO BAR BAZ I
35+
No Operation
36+
37+
Keyword deduplicate
38+
[Tags] TAG_A TAG_B TAG_C # comment
39+
No Operation
40+
41+
Keyword deduplicate and normalize case
42+
[Tags] FOO_BAR_BAZ_A FOO_BAR_BAZ_B FOO_BAR_BAZ_C FOOBARBAZD FOOBARBAZE FOOBARBAZF FOO BAR BAZ G FOO BAR BAZ H FOO BAR BAZ I
43+
No Operation
44+
45+
One Tag Keyword
46+
[Tags] ONE_TAG_VARIOUS CASES
47+
No Operation
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
*** Settings ***
2+
Documentation OrderTags acceptance tests
3+
Force Tags Tag1 tag1 tag2 tag2 tag3 tag4
4+
Default Tags Tag1 tag1 tag2 tag2 tag3 tag4
5+
6+
*** Test Cases ***
7+
No tags
8+
Keyword no tags
9+
10+
Different cases
11+
[Tags] Tag1 tag1 TAG1 other_tag
12+
Keyword different cases
13+
14+
Same cases
15+
[Tags] tag2 tag2 other_tag
16+
Keyword same cases
17+
18+
Not duplicates
19+
[Tags] tag3 tag4
20+
Keyword not duplicates
21+
22+
One Tag
23+
[Tags] tag5
24+
One Tag Keyword
25+
26+
*** Keywords ***
27+
Keyword no tags
28+
No Operation
29+
30+
Keyword same cases
31+
[Tags] tag2 tag2 other_tag
32+
No Operation
33+
34+
Keyword different cases
35+
[Tags] Tag1 tag1 TAG1 other_tag
36+
No Operation
37+
38+
Keyword not duplicates
39+
[Tags] tag3 tag4
40+
No Operation
41+
42+
One Tag Keyword
43+
[Tags] tag5
44+
No Operation
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
*** Settings ***
2+
Documentation OrderTags acceptance tests
3+
Force Tags tag1 Tag2 TAG3 tag4 tag4 tag5 TAG5 # comment
4+
Default Tags tag1 Tag2 TAG3 tag4 tag4 tag5 TAG5 # comment
5+
6+
*** Test Cases ***
7+
No tags
8+
Keyword no tags
9+
10+
Normalize case
11+
[Tags] foo_bar_baz_a Foo_Bar_Baz_b FOO_BAR_BAZ_c foobarbazd FooBarBaze FOOBARBAZf foo bar baz g Foo Bar Baz h FOO BAR BAZ i
12+
Keyword normalize case
13+
14+
Deduplicate
15+
[Tags] tag_a tag_a tag_b tag_c
16+
Keyword deduplicate
17+
18+
Deduplicate and normalize case
19+
[Tags] foo_bar_baz_a foo_bar_baz_A Foo_Bar_Baz_b FOO_BAR_BAZ_c foobarbazd FooBarBaze FOOBARBAZf foo bar baz g Foo Bar Baz h FOO BAR BAZ i
20+
Keyword deduplicate and normalize case
21+
22+
One Tag
23+
[Tags] One_Tag_various CASES
24+
One Tag Keyword
25+
26+
Multiline tags
27+
[Tags] tag1
28+
... Tag2
29+
... TAG3 # comment1
30+
... tag4
31+
... tag4
32+
... tag5 # comment2
33+
... TAG5
34+
35+
*** Keywords ***
36+
Keyword no tags
37+
No Operation
38+
39+
Keyword normalize case
40+
[Tags] foo_bar_baz_a Foo_Bar_Baz_b FOO_BAR_BAZ_c foobarbazd FooBarBaze FOOBARBAZf foo bar baz g Foo Bar Baz h FOO BAR BAZ i
41+
No Operation
42+
43+
Keyword deduplicate
44+
[Tags] tag_a tag_a tag_b tag_c # comment
45+
No Operation
46+
47+
Keyword deduplicate and normalize case
48+
[Tags] foo_bar_baz_a foo_bar_baz_A Foo_Bar_Baz_b FOO_BAR_BAZ_c foobarbazd FooBarBaze FOOBARBAZf foo bar baz g Foo Bar Baz h FOO BAR BAZ i
49+
No Operation
50+
51+
One Tag Keyword
52+
[Tags] One_Tag_various CASES
53+
No Operation

0 commit comments

Comments
 (0)