Skip to content

Commit 8f7c4be

Browse files
committed
requested changes
1 parent 47cdb6e commit 8f7c4be

2 files changed

Lines changed: 58 additions & 43 deletions

File tree

utils/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
pyyaml
2+
pandas

utils/validate_yaml.py

Lines changed: 57 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,18 @@
11
import yaml
2+
23
import sys
4+
from pathlib import Path
5+
6+
# Add parent directory to sys.path
7+
parent = Path(__file__).resolve().parent.parent
8+
sys.path.insert(0, str(parent))
9+
10+
# Now you can import normally
11+
from yaml_to_html import default_columns as REQUIRED_FIELDS
312

4-
# Define the required fields your YAML must have
5-
REQUIRED_FIELDS = [
6-
"name",
7-
"suite/generator/single",
8-
"objectives",
9-
"dimensionality",
10-
"variable type",
11-
"constraints",
12-
"dynamic",
13-
"noise",
14-
"multimodal",
15-
"multi-fidelity",
16-
"reference",
17-
"implementation",
18-
"source (real-world/artificial)",
19-
"textual description",
20-
]
21-
22-
UNIQUE_FIELDS = ["name", "reference", "implementation"]
13+
OPTIONAL_FIELDS = ["multimodal"]
14+
UNIQUE_FIELDS = ["name"]
15+
UNIQUE_WARNING_FIELDS = ["reference", "implementation"]
2316
PROBLEMS_FILE = "problems.yaml"
2417

2518

@@ -29,34 +22,48 @@ def read_data(filepath):
2922
data = yaml.safe_load(f)
3023
return 0, data
3124
except FileNotFoundError:
32-
print(f"File not found: {filepath}")
25+
print(f"::error::File not found: {filepath}")
3326
return 1, None
3427
except yaml.YAMLError as e:
35-
print(f"YAML syntax error: {e}")
28+
print(f"::error::YAML syntax error: {e}")
3629
return 1, None
3730

3831

3932
def check_format(data):
40-
if len(data) != 1:
41-
print("YAML file should contain exactly one top-level document.")
42-
return False
43-
if not isinstance(data[0], dict):
44-
print("Top-level document should be a dictionary.")
33+
num_problems = len(data)
34+
if len(data) < 1:
35+
print("::error::YAML file should contain at least one top level entry.")
4536
return False
37+
print(f"::notice::YAML file contains {num_problems} top-level entries.")
38+
unique_fields = []
39+
for i, entry in enumerate(data):
40+
if not isinstance(entry, dict):
41+
print(f"::error::Entry {i} is not a dictionary.")
42+
return False
43+
unique_fields.append({k: v for k, v in entry.items() if k in UNIQUE_FIELDS})
44+
for k in UNIQUE_FIELDS:
45+
values = [entry[k] for entry in unique_fields]
46+
if len(values) != len(set(values)):
47+
print(f"::error::Field '{k}' must be unique across all entries.")
48+
return False
4649
return True
4750

4851

4952
def check_fields(data):
50-
if len(data) != len(REQUIRED_FIELDS):
51-
print(f"YAML file should contain exactly {len(REQUIRED_FIELDS)} fields.")
52-
return False
5353
missing = [field for field in REQUIRED_FIELDS if field not in data]
5454
if missing:
55-
print(f"Missing required fields: {', '.join(missing)}")
55+
print(f"::error::Missing required fields: {', '.join(missing)}")
5656
return False
57+
new_fields = [
58+
field for field in data if field not in REQUIRED_FIELDS + OPTIONAL_FIELDS
59+
]
60+
if new_fields:
61+
print(f"::warning::New field added: {', '.join(new_fields)}")
5762
# Check that the name is not still template
5863
if data.get("name") == "template":
59-
print("Please change the 'name' field from 'template' to a unique name.")
64+
print(
65+
"::error::Please change the 'name' field from 'template' to a unique name."
66+
)
6067
return False
6168
return True
6269

@@ -65,18 +72,24 @@ def check_novelty(data):
6572
# Load existing problems
6673
read_status, existing_data = read_data(PROBLEMS_FILE)
6774
if read_status != 0:
68-
print("Could not read existing problems for novelty check.")
75+
print("::eror::Could not read existing problems for novelty check.")
6976
return False
7077
assert existing_data is not None
71-
for field in UNIQUE_FIELDS:
78+
for field in UNIQUE_FIELDS or UNIQUE_WARNING_FIELDS:
7279
existing_values = {
7380
entry.get(field) for entry in existing_data if isinstance(entry, dict)
7481
}
7582
if data.get(field) in existing_values:
76-
print(
77-
f"Field '{field}' with value '{data.get(field)}' already exists. Please choose a unique value."
78-
)
79-
return False
83+
if field in UNIQUE_WARNING_FIELDS:
84+
print(
85+
f"::warning::Field '{field}' with value '{data.get(field)}' already exists. Consider choosing a unique value."
86+
)
87+
continue
88+
elif field in UNIQUE_FIELDS:
89+
print(
90+
f"::error::Field '{field}' with value '{data.get(field)}' already exists. Please choose a unique value."
91+
)
92+
return False
8093
return True
8194

8295

@@ -86,12 +99,13 @@ def validate_yaml(filepath):
8699
sys.exit(1)
87100
if not check_format(data):
88101
sys.exit(1)
89-
assert data is not None and len(data) == 1
90-
new_data = data[0] # Extract the single top-level entry
102+
assert data is not None
91103

92-
# Check required and unique fields
93-
if not check_fields(new_data) or not check_novelty(new_data):
94-
sys.exit(1)
104+
for i, new_data in enumerate(data): # Iterate through each top-level entry
105+
# Check required and unique fields
106+
if not check_fields(new_data) or not check_novelty(new_data):
107+
print(f"::error::Validation failed for entry {i+1}.")
108+
sys.exit(1)
95109

96110
# YAML is valid if we reach this point
97111
print("YAML syntax is valid.")
@@ -100,7 +114,7 @@ def validate_yaml(filepath):
100114

101115
if __name__ == "__main__":
102116
if len(sys.argv) < 2:
103-
print("Usage: python validate_yaml.py <yourfile.yaml>")
117+
print("::error::Usage: python validate_yaml.py <yourfile.yaml>")
104118
sys.exit(1)
105119

106120
filepath = sys.argv[1]

0 commit comments

Comments
 (0)