diff --git a/src/usethis/_integrations/file/yaml/io_.py b/src/usethis/_integrations/file/yaml/io_.py index 3f38f676..055816e3 100644 --- a/src/usethis/_integrations/file/yaml/io_.py +++ b/src/usethis/_integrations/file/yaml/io_.py @@ -474,7 +474,12 @@ def edit_yaml( except YAMLError as err: msg = f"Error reading '{yaml_path}':\n{err}" raise YAMLDecodeError(msg) from None + + start_empty = not yaml_document.content yield yaml_document + if start_empty and not yaml_document.content: + # No change + return yaml_document.roundtripper.dump(yaml_document.content, stream=yaml_path) diff --git a/src/usethis/_integrations/pre_commit/io_.py b/src/usethis/_integrations/pre_commit/io_.py index a5aec3bb..f8b11a87 100644 --- a/src/usethis/_integrations/pre_commit/io_.py +++ b/src/usethis/_integrations/pre_commit/io_.py @@ -5,6 +5,7 @@ from typing import TYPE_CHECKING from pydantic import ValidationError +from ruamel.yaml.comments import CommentedMap from usethis._config import usethis_config from usethis._console import tick_print @@ -15,8 +16,6 @@ if TYPE_CHECKING: from collections.abc import Generator - from ruamel.yaml.comments import CommentedMap - from usethis._integrations.file.yaml.io_ import YAMLLiteral @@ -62,6 +61,9 @@ def edit_pre_commit_config_yaml() -> Generator[PreCommitConfigYAMLDocument, None def _validate_config(ruamel_content: YAMLLiteral) -> JsonSchemaForPreCommitConfigYaml: + if isinstance(ruamel_content, CommentedMap) and not ruamel_content: + ruamel_content = CommentedMap({"repos": []}) + try: return JsonSchemaForPreCommitConfigYaml.model_validate(ruamel_content) except ValidationError as err: diff --git a/tests/usethis/_integrations/pre_commit/test_pre_commit_io_.py b/tests/usethis/_integrations/pre_commit/test_pre_commit_io_.py index 60100b3a..ab1850d6 100644 --- a/tests/usethis/_integrations/pre_commit/test_pre_commit_io_.py +++ b/tests/usethis/_integrations/pre_commit/test_pre_commit_io_.py @@ -1,11 +1,6 @@ from pathlib import Path -import pytest - -from usethis._integrations.pre_commit.io_ import ( - PreCommitConfigYAMLConfigError, - edit_pre_commit_config_yaml, -) +from usethis._integrations.pre_commit.io_ import edit_pre_commit_config_yaml from usethis._test import change_cwd @@ -35,14 +30,27 @@ def test_unchanged(self, tmp_path: Path): # Assert assert (tmp_path / ".pre-commit-config.yaml").read_text() == content_str - def test_empty_is_invalid(self, tmp_path: Path): + def test_start_with_empty_file(self, tmp_path: Path): # Arrange (tmp_path / ".pre-commit-config.yaml").write_text("") - # Act, Assert + # Act with ( change_cwd(tmp_path), - pytest.raises(PreCommitConfigYAMLConfigError), - edit_pre_commit_config_yaml(), + edit_pre_commit_config_yaml() as doc, ): + doc.content["repos"] = [] + + # Assert + assert (tmp_path / ".pre-commit-config.yaml").read_text() == "repos: []\n" + + def test_empty_valid_but_unchanged(self, tmp_path: Path): + # Arrange + (tmp_path / ".pre-commit-config.yaml").write_text("") + + # Act + with change_cwd(tmp_path), edit_pre_commit_config_yaml(): pass + + # Assert + assert (tmp_path / ".pre-commit-config.yaml").read_text() == ""