-
Notifications
You must be signed in to change notification settings - Fork 16
/
check_year_bundle.py
executable file
·134 lines (100 loc) · 4.45 KB
/
check_year_bundle.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/env python3
import os
import sys
import argparse
import pathlib
import json
from dataclasses import dataclass
import uuid
@dataclass
class Results:
uuid_errors: int = 0
bad_file_errors: int = 0
duplicate_version_errors: int = 0
inconsistent_version_errors: int = 0
missing_description_errors: int = 0
missing_website_errors: int = 0
uncovered_file_errors: int = 0
def is_valid(self):
valid = True
valid = valid and self.uuid_errors == 0
valid = valid and self.bad_file_errors == 0
valid = valid and self.duplicate_version_errors == 0
valid = valid and self.inconsistent_version_errors == 0
valid = valid and self.missing_description_errors == 0
valid = valid and self.missing_website_errors == 0
valid = valid and self.uncovered_file_errors == 0
return valid
def check_year_bundle(year: int) -> Results:
bundled_json_file = pathlib.Path(f"{year}.json")
json_data = json.loads(bundled_json_file.read_text())
vendordep_versions = {} # Name -> set[version]
vendordep_uuid = {} # Name -> UUID
results = Results()
covered_files = set()
for dep in json_data:
if dep["name"] not in vendordep_versions:
vendordep_versions[dep["name"]] = set()
resolved_path = dep["path"]
file_json_data = None
# Check file existence
if not os.path.exists(resolved_path):
print(f"{dep['path']} - Could not find file")
results.bad_file_errors += 1
else:
file_json_data = json.load(open(resolved_path))
covered_files.add(resolved_path)
# Check description
if "description" not in dep:
print(f"{dep['path']} - Missing description")
results.missing_description_errors += 1
# Check website
if "website" not in dep:
print(f"{dep['path']} - Missing documentation website")
results.missing_website_errors += 1
# Check version
if dep["version"] in vendordep_versions[dep["name"]]:
print(f"{dep['path']} - Duplicated version {dep['version']}")
results.duplicate_version_errors += 1
vendordep_versions[dep["name"]].add(dep["version"])
if file_json_data is not None and file_json_data["version"] != dep["version"]:
print(f"{dep['path']} - Version {dep['version']} does not match the version in the file {file_json_data['version']}")
results.inconsistent_version_errors +=1
# Check UUID
if dep["name"] not in vendordep_uuid:
vendordep_uuid[dep["name"]] = dep["uuid"]
if vendordep_uuid[dep["name"]] != dep["uuid"]:
print(f"{dep['path']} - UUID {dep['uuid']} has has changed from previously seen UUID {vendordep_uuid[dep['name']]}")
results.uuid_errors += 1
if file_json_data is not None and file_json_data["uuid"] != dep["uuid"]:
print(f"{dep['path']} - UUID {dep['uuid']} does not match the UUID in the file {file_json_data['uuid']}")
results.uuid_errors += 1
try:
uuid.UUID(dep["uuid"])
except:
print(f"{dep['path']} - UUID {dep['uuid']} is invalid")
results.uuid_errors += 1
# Look for uncovered files
all_files = set([os.path.join(str(year), x) for x in os.listdir(str(year))])
uncovered_files = all_files.difference(covered_files)
for f in uncovered_files:
print(f"File {f} is not represented in the year bundle")
results.uncovered_file_errors += 1
# Check that UUID's are unique across vendordeps
if len(vendordep_uuid) != len(set(vendordep_uuid.values())):
print(f"There are a different number of vendordeps ({len(vendordep_uuid)}) than there are UUIDs ({len(set(vendordep_uuid.values()))}), indicating UUID's have been reused between vendordeps")
results.uuid_errors += 1
# Print known versions
print("Known versions:")
for k in vendordep_versions:
print(f" {k} - {vendordep_versions[k]}")
return results
def main():
parser = argparse.ArgumentParser(description='Checks a vendor json file')
parser.add_argument('--year', '-y', required=True, help='FRC competition season year')
args = parser.parse_args(sys.argv[1:])
results = check_year_bundle(args.year)
print(results)
sys.exit(results.is_valid(args.disable_uuid_check))
if __name__ == "__main__":
main()