Action-Component-Check-Demo/.allspice/component_validation.py
2024-08-28 19:33:11 -04:00

113 lines
4.2 KiB
Python
Executable File

#!/usr/bin/env python3
import csv
import sys
import logging
from typing import Optional
from jinja2 import Environment, FileSystemLoader
components_csv_path = sys.argv[1]
MIN_TEMP_C: int = -10
MAX_TEMP_C: int = 70
class ComponentsWarning:
def __init__(self):
self.part_number: Optional[str] = None
self.refs: list[str] = []
self.warnings: list[str] = []
report_context = {
"component_warnings": [],
"warning_count": 0,
"total_components": 0,
"min_temp": MIN_TEMP_C,
"max_temp": MAX_TEMP_C,
}
class CustomFormatter(logging.Formatter):
grey = "\x1b[38;20m"
yellow = "\x1b[33;20m"
red = "\x1b[31;20m"
reset = "\x1b[0m"
format = "%(levelname)s - %(message)s (%(filename)s:%(lineno)d)"
FORMATS = {
logging.DEBUG: grey + format + reset,
logging.INFO: grey + format + reset,
logging.WARNING: yellow + format + reset,
logging.ERROR: red + format + reset,
}
def format(self, record):
log_fmt = self.FORMATS.get(record.levelno)
formatter = logging.Formatter(log_fmt)
return formatter.format(record)
# Add formatted logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
ch = logging.StreamHandler()
ch.setFormatter(CustomFormatter())
logger.addHandler(ch)
with open(components_csv_path, newline="") as components_csv:
spamreader = csv.DictReader(components_csv, delimiter=",")
component_count = 0
for row in spamreader:
component_count += 1
component = ComponentsWarning()
component.refs = row['Designator'].split(', ')
if row["Part Number"] == '':
component.warnings.append("No `Part Number` attribute!")
elif row["Part Number"] == "NA":
logger.warning(f"Designators(s) {row['Designator']} have `NA` Part Number!")
component.warnings.append("`NA` `Part Number` attribute!")
elif row["Part Number"].startswith("TMP"):
logger.warning(
f"Designator(s) {row['Designator']} have temporary Part Number!"
)
component.warnings.append("`TMP*` `Part Number` attribute!")
else:
component.part_number = row["Part Number"]
if row["Temperature"] == "":
logger.warning(
f"Designators(s) {row['Designator']} have no `Temperature` attribute!"
)
component.warnings.append("No `Temperature` attribute!")
else:
try:
min_temp, max_temp = [int(x.strip("¡ãC ")) for x in row["Temperature"].split(" to ")]
except ValueError:
logger.warning(
f"Designators(s) {row['Designator']} have malformed `Temperature` attribute: !"
)
component.warnings.append(f"Malformed `Temperature` attribute: `{row['Temperature']}`!")
else:
if min_temp > MIN_TEMP_C:
logger.warning(
f"Designators(s) {row['Designator']} minimum operating temperate `{min_temp}°C` exceeds requirement of `{MIN_TEMP_C}°C`!"
)
component.warnings.append(f"Minimum operating temperate `{min_temp}°C` exceeds requirement of `{MIN_TEMP_C}°C`!")
if max_temp < MAX_TEMP_C:
logger.warning(
f"Designators(s) {row['Designator']} maximum operating temperate `{max_temp}°C` doesn't meet requirement of `{MAX_TEMP_C}°C`!"
)
component.warnings.append(f"Maximum operating temperate `{max_temp}°C` doesn't meet requirement of `{MAX_TEMP_C}°C`!")
if len(component.warnings):
report_context["component_warnings"].append(component)
report_context["warning_count"] += 1
report_context["total_components"] = component_count
# Load Jinja with output HTML template
template_env = Environment(loader=FileSystemLoader("./.allspice/report_template/"), trim_blocks=True, lstrip_blocks=True)
template = template_env.get_template("report.template.md")
with open("./.allspice/report.md", mode="w", encoding="utf-8") as report_file:
report_file.write(template.render(report_context))