From c507b9b29bd3047cbc2db88e976b4a622f9fb626 Mon Sep 17 00:00:00 2001 From: Roman Vlasenko Date: Fri, 19 May 2023 20:57:19 +0300 Subject: [PATCH 1/6] Adjustable whitelines --- src/yamlfix/adapters.py | 7 ++-- src/yamlfix/model.py | 1 + tests/unit/test_adapter_yaml.py | 71 +++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/src/yamlfix/adapters.py b/src/yamlfix/adapters.py index 189294c..a256651 100644 --- a/src/yamlfix/adapters.py +++ b/src/yamlfix/adapters.py @@ -616,7 +616,7 @@ def _fix_whitelines(self, source_code: str) -> str: - 0 whiteline is allowed - Exactly `self.config.comments_whitelines` whitelines are allowed - This method removes extraneous whitelines that are not immediately followed by + This method also adjusts amount of whitelines that are not immediately followed by a comment. Args: @@ -626,12 +626,13 @@ def _fix_whitelines(self, source_code: str) -> str: Source code with appropriate whitelines standards. """ config = self.config + n_whitelines = config.whitelines n_whitelines_from_content = config.comments_whitelines re_whitelines_with_comments = "\n\n+[\t ]{0,}[#]" re_whitelines_with_no_comments = "\n\n+[\t ]{0,}[^#\n\t ]" - remove_whitelines = partial(self._replace_whitelines, n_whitelines=0) + adjust_whitelines = partial(self._replace_whitelines, n_whitelines=n_whitelines) replace_by_n_whitelines = partial( self._replace_whitelines, n_whitelines=n_whitelines_from_content, @@ -639,7 +640,7 @@ def _fix_whitelines(self, source_code: str) -> str: source_code = re.sub( pattern=re_whitelines_with_no_comments, - repl=remove_whitelines, + repl=adjust_whitelines, string=source_code, ) source_code = self._fix_section_whitelines(source_code) diff --git a/src/yamlfix/model.py b/src/yamlfix/model.py index 0737189..f8c1f87 100644 --- a/src/yamlfix/model.py +++ b/src/yamlfix/model.py @@ -20,6 +20,7 @@ class YamlfixConfig(ConfigSchema): comments_min_spaces_from_content: int = 2 comments_require_starting_space: bool = True comments_whitelines: int = 1 + whitelines: int = 0 section_whitelines: int = 0 config_path: Optional[str] = None explicit_start: bool = True diff --git a/tests/unit/test_adapter_yaml.py b/tests/unit/test_adapter_yaml.py index 24d66b8..cc20c37 100644 --- a/tests/unit/test_adapter_yaml.py +++ b/tests/unit/test_adapter_yaml.py @@ -830,3 +830,74 @@ def test_section_whitelines_begin_no_explicit_start(self) -> None: result = fix_code(source, config) assert result == fixed_source + + def test_whitelines_collapsed(self) -> None: + """Checks that whitelines are collapsed by default.""" + source = dedent( + """\ + key: value + + dict: + key: value + nested_dict: + - key: value + key2: value2 + + - key: value + """ + ) + fixed_source = dedent( + """\ + --- + key: value + dict: + key: value + nested_dict: + - key: value + key2: value2 + - key: value + """ + ) + config = YamlfixConfig() + + result = fix_code(source, config) + + assert result == fixed_source + + def test_whitelines_adjusted_to_value(self) -> None: + """Checks that amount of whitelines are in line with the config value.""" + source = dedent( + """\ + key: value + + dict: + key: value + + + nested_list: + - key: value + key2: value2 + + - key: value + """ + ) + fixed_source = dedent( + """\ + --- + key: value + dict: + key: value + + nested_list: + - key: value + key2: value2 + + - key: value + """ + ) + config = YamlfixConfig() + config.whitelines = 1 + + result = fix_code(source, config) + + assert result == fixed_source From 67f09a7681714bbe53cc862d31cb391bfa4a7c75 Mon Sep 17 00:00:00 2001 From: Roman Vlasenko Date: Sat, 20 May 2023 15:39:21 +0300 Subject: [PATCH 2/6] Make _fix_flow_style_lists preserve newlines --- src/yamlfix/adapters.py | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/src/yamlfix/adapters.py b/src/yamlfix/adapters.py index a256651..bf9229e 100644 --- a/src/yamlfix/adapters.py +++ b/src/yamlfix/adapters.py @@ -353,9 +353,9 @@ def fix(self, source_code: str) -> str: self._restore_jinja_variables, self._restore_double_exclamations, self._fix_comments, + self._fix_flow_style_lists, self._fix_whitelines, self._fix_top_level_lists, - self._fix_flow_style_lists, self._add_newline_at_end_of_file, ] @@ -478,7 +478,7 @@ def _fix_flow_style_lists(source_code: str) -> str: ``` This function moves the closing bracket to the end of the flow-style - list definition. + list definition and positions the newlines after the closing bracket. Args: source_code: Source code to be corrected. @@ -487,26 +487,9 @@ def _fix_flow_style_lists(source_code: str) -> str: Corrected source code. """ log.debug("Fixing flow-style lists...") - source_lines = source_code.splitlines() - reversed_fixed_source_lines: List[str] = [] - - should_append_square_brackets: bool = False - for line in reversed(source_lines): - if line == "]": - should_append_square_brackets = True - continue - - if line == "": - reversed_fixed_source_lines.append(line) - continue - - if should_append_square_brackets: - should_append_square_brackets = False - reversed_fixed_source_lines.append(line + "]") - else: - reversed_fixed_source_lines.append(line) - - return "\n".join(reversed(reversed_fixed_source_lines)) + pattern = r"\[(?P.*)(?P\n+)]" + replacement = r"[\g]\g" + return re.sub(pattern, repl=replacement, string=source_code) @staticmethod def _fix_truthy_strings(source_code: str) -> str: From 6a1cefd845d78223737cb600ababf60b7851a068 Mon Sep 17 00:00:00 2001 From: Roman Vlasenko Date: Sat, 20 May 2023 15:41:41 +0300 Subject: [PATCH 3/6] Make debug logs test not depend on the order of emitted logs by comparing sets --- tests/unit/test_services.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit/test_services.py b/tests/unit/test_services.py index 125b633..cbf6bf0 100644 --- a/tests/unit/test_services.py +++ b/tests/unit/test_services.py @@ -469,7 +469,7 @@ def test_fix_code_functions_emit_debug_logs( fix_code("") # act - expected_logs = [ + expected_logs = { "Setting up ruamel yaml 'quote simple values' configuration...", "Setting up ruamel yaml 'sequence flow style' configuration...", "Running ruamel yaml base configuration...", @@ -483,8 +483,8 @@ def test_fix_code_functions_emit_debug_logs( "Fixing comments...", "Fixing top level lists...", "Fixing flow-style lists...", - ] - assert caplog.messages == expected_logs + } + assert set(caplog.messages) == expected_logs for record in caplog.records: assert record.levelname == "DEBUG" From be8c09c2c3b6b6ce2a0f38ebdf0d6806abd37235 Mon Sep 17 00:00:00 2001 From: Roman Vlasenko Date: Sat, 20 May 2023 15:43:30 +0300 Subject: [PATCH 4/6] Make sure that there's only one newline at the end of a file --- src/yamlfix/adapters.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/yamlfix/adapters.py b/src/yamlfix/adapters.py index bf9229e..0a125e9 100644 --- a/src/yamlfix/adapters.py +++ b/src/yamlfix/adapters.py @@ -706,7 +706,15 @@ def _restore_double_exclamations(source_code: str) -> str: @staticmethod def _add_newline_at_end_of_file(source_code: str) -> str: - return source_code + "\n" + """Ensures that the file ends with exactly one newline. + + Args: + source_code: Source code to be corrected. + + Returns: + Corrected source code. + """ + return source_code.rstrip() + "\n" @staticmethod def _fix_jinja_variables(source_code: str) -> str: From 1e0d15d23b09025349c5680b913f7650d3c440b4 Mon Sep 17 00:00:00 2001 From: Roman Vlasenko Date: Sat, 20 May 2023 15:56:51 +0300 Subject: [PATCH 5/6] Test adjustable whitelines together with flow-style --- tests/unit/test_adapter_yaml.py | 38 +++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/unit/test_adapter_yaml.py b/tests/unit/test_adapter_yaml.py index cc20c37..f8b28f1 100644 --- a/tests/unit/test_adapter_yaml.py +++ b/tests/unit/test_adapter_yaml.py @@ -901,3 +901,41 @@ def test_whitelines_adjusted_to_value(self) -> None: result = fix_code(source, config) assert result == fixed_source + + def test_enforcing_flow_style_together_with_adjustable_newlines(self) -> None: + """Checks that transforming block style sequences to flow style together with + newlines adjusting produces correct result. + """ + source = dedent( + """\ + --- + dict: + nested_dict: + key: value + key2: + - list_item + + + nested_dict2: + key: value + """ + ) + fixed_source = dedent( + """\ + --- + dict: + nested_dict: + key: value + key2: [list_item] + + nested_dict2: + key: value + """ + ) + config = YamlfixConfig() + config.whitelines = 1 + config.sequence_style = YamlNodeStyle.FLOW_STYLE + + result = fix_code(source, config) + + assert result == fixed_source From cb7969fc32509ec1ea4d7c96cb9f40d3133968cd Mon Sep 17 00:00:00 2001 From: Roman Vlasenko Date: Sat, 20 May 2023 16:41:54 +0300 Subject: [PATCH 6/6] Document whitelines adjusting --- docs/index.md | 17 +++++++++++++++++ src/yamlfix/adapters.py | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index 359d9f1..3ba9813 100644 --- a/docs/index.md +++ b/docs/index.md @@ -194,6 +194,23 @@ export YAMLFIX_COMMENTS_REQUIRE_STARTING_SPACE="true" This option enforces a space between the comment indicator (`#`) and the first character in the comment. It implements the enforcement of the yamllint rule `rules.comments.require-starting-space` - see: https://yamllint.readthedocs.io/en/stable/rules.html#module-yamllint.rules.comments +### Whitelines Adjusting + +Default: `whitelines: int = 0`
+Environment variable override: +```bash +export YAMLFIX_WHITELINES="0" +``` + +This option allows to keep a speficied number of whitelines between lines. + +It's useful if, for one, you like to separate GitHub Actions job steps or Docker-Compose +service definitions with a blank line. + +Bear in mind that, like **Comments Whitelines**, it won't insert whitelines if there's no +whitelines in the first place. It will only fix 1 or more whitelines to the desired +amount (or remove them completely by default). + ### Comments Whitelines Default: `comments_whitelines: int = 1`
diff --git a/src/yamlfix/adapters.py b/src/yamlfix/adapters.py index 0a125e9..c5ce0ea 100644 --- a/src/yamlfix/adapters.py +++ b/src/yamlfix/adapters.py @@ -599,8 +599,8 @@ def _fix_whitelines(self, source_code: str) -> str: - 0 whiteline is allowed - Exactly `self.config.comments_whitelines` whitelines are allowed - This method also adjusts amount of whitelines that are not immediately followed by - a comment. + This method also adjusts amount of whitelines that are not immediately followed + by a comment. Args: self: Source code to be corrected.