Skip to content

Commit 3e52900

Browse files
committed
Add support for multiple yaml documents in a file
1 parent 191ccb2 commit 3e52900

File tree

6 files changed

+88
-6
lines changed

6 files changed

+88
-6
lines changed

.yamllint.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ ignore: |
55
/.venv
66
/examples
77
tests/unit/sdk/test_data/schema_encoding_error.yml
8+
tests/unit/sdk/test_data/multiple_files_valid_not_valid.yml
89
910
rules:
1011
new-lines: disable

infrahub_sdk/yaml.py

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import yaml
88
from pydantic import BaseModel, Field
99
from typing_extensions import Self
10+
from yaml.parser import ParserError
1011

1112
from .exceptions import FileNotValidError
1213
from .utils import find_files, read_file
@@ -31,6 +32,8 @@ class InfrahubFileData(BaseModel):
3132
class LocalFile(BaseModel):
3233
identifier: str | None = None
3334
location: Path
35+
multiple_documents: bool = False
36+
document_position: int | None = None
3437
content: dict | None = None
3538
valid: bool = True
3639
error_message: str | None = None
@@ -57,20 +60,52 @@ def load_content(self) -> None:
5760
def validate_content(self) -> None:
5861
pass
5962

63+
@classmethod
64+
def load_file_from_disk(cls, path: Path) -> list[Self]:
65+
yaml_files: list[Self] = []
66+
67+
try:
68+
file_content = read_file(path)
69+
70+
has_multiple_document = bool(file_content.count("---") > 1)
71+
72+
if has_multiple_document:
73+
for content in yaml.safe_load_all(file_content):
74+
yaml_files.append(cls(location=path, multiple_documents=has_multiple_document, content=content))
75+
else:
76+
yaml_files.append(
77+
cls(location=path, multiple_documents=has_multiple_document, content=yaml.safe_load(file_content))
78+
)
79+
except FileNotValidError as exc:
80+
yaml_files.append(
81+
cls(location=path, multiple_documents=has_multiple_document, error_message=exc.message, valid=False)
82+
)
83+
except (yaml.YAMLError, ParserError):
84+
yaml_files.append(
85+
cls(
86+
location=path,
87+
multiple_documents=has_multiple_document,
88+
error_message="Invalid YAML/JSON file",
89+
valid=False,
90+
)
91+
)
92+
93+
if has_multiple_document:
94+
for idx, file in enumerate(yaml_files):
95+
file.document_position = idx + 1
96+
97+
return yaml_files
98+
6099
@classmethod
61100
def load_from_disk(cls, paths: list[Path]) -> list[Self]:
62101
yaml_files: list[Self] = []
63102
for file_path in paths:
64103
if file_path.is_file():
65-
yaml_file = cls(location=file_path)
66-
yaml_file.load_content()
67-
yaml_files.append(yaml_file)
104+
yaml_files.extend(cls.load_file_from_disk(path=file_path))
68105
elif file_path.is_dir():
69106
files = find_files(extension=["yaml", "yml", "json"], directory=file_path)
70107
for item in files:
71-
yaml_file = cls(location=item)
72-
yaml_file.load_content()
73-
yaml_files.append(yaml_file)
108+
yaml_files.extend(cls.load_file_from_disk(path=item))
74109
else:
75110
raise FileNotValidError(name=str(file_path), message=f"{file_path} does not exist!")
76111

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
version: "1.0"
3+
nodes:
4+
- name: Node
5+
namespace: Testing
6+
---
7+
version: "1.0"
8+
nodes:
9+
- name: Node2
10+
namespace: Testing
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
version: "1.0"
3+
nodes:
4+
- name: Node
5+
namespace: Testing
6+
---
7+
version: "1.0"
8+
nodes:
9+
- name: Node2
10+
namespace: Testing
11+
- name: Node3
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
version: "1.0"
3+
nodes:
4+
- name: Node
5+
namespace: Testing

tests/unit/sdk/test_yaml.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,23 @@ def test_read_incorrect_encoding() -> None:
1919
yaml_file.load_content()
2020
assert not yaml_file.valid
2121
assert yaml_file.error_message == f"Unable to read {file} with utf-8 encoding"
22+
23+
24+
def test_read_multiple_files() -> None:
25+
file = here / "test_data/multiple_files_valid.yml"
26+
yaml_files = YamlFile.load_file_from_disk(path=file)
27+
assert len(yaml_files) == 2
28+
assert yaml_files[0].document_position == 1
29+
assert yaml_files[0].valid is True
30+
assert yaml_files[1].document_position == 2
31+
assert yaml_files[1].valid is True
32+
33+
34+
def test_read_multiple_files_invalid() -> None:
35+
file = here / "test_data/multiple_files_valid_not_valid.yml"
36+
yaml_files = YamlFile.load_file_from_disk(path=file)
37+
assert len(yaml_files) == 2
38+
assert yaml_files[0].document_position == 1
39+
assert yaml_files[0].valid is True
40+
assert yaml_files[1].document_position == 2
41+
assert yaml_files[1].valid is False

0 commit comments

Comments
 (0)