simfile-smoketest/smoketest.py
2022-07-17 22:32:44 -07:00

134 lines
3.6 KiB
Python

import argparse
import os
import pprint
import shelve
import traceback
from typing import Counter, Dict, List, Optional
import simfile
from simfile.notes import NoteData
from simfile.notes.group import group_notes
from simfile.notes.timed import time_notes
from simfile.ssc import SSCChart
from simfile.timing.engine import TimingData
from simfile.timing.displaybpm import displaybpm
class SimfileError:
context: str
traceback: Optional[str]
def __init__(self, context: str):
self.context = context
self.traceback = traceback.format_exc()
def __repr__(self):
return f"{self.context}: {self.traceback}"
def check_simfile(filename: str) -> List[SimfileError]:
errors = []
try:
sim = simfile.open(filename)
except Exception:
errors.append(SimfileError("parse"))
return errors
timing_data = None
try:
timing_data = TimingData.from_simfile(sim)
except Exception:
errors.append(SimfileError("timing"))
try:
displaybpm(sim)
except Exception:
errors.append(SimfileError("displaybpm"))
for c, chart in enumerate(sim.charts):
try:
note_data = NoteData.from_chart(chart)
except Exception:
errors.append(SimfileError(f"chart {c} note_data"))
try:
for _ in group_notes(note_data, join_heads_to_tails=True):
pass
except Exception:
errors.append(SimfileError(f"chart {c} group_notes"))
if isinstance(chart, SSCChart):
try:
displaybpm(sim, chart)
except Exception:
errors.append(SimfileError(f"chart {c} displaybpm"))
# skip the remaining chart tests if timing data parsing failed
if timing_data is None:
continue
if isinstance(chart, SSCChart):
try:
timing_data = TimingData.from_simfile(sim, chart)
except Exception:
errors.append(SimfileError(f"chart {c} timing"))
try:
for _ in time_notes(note_data, timing_data):
pass
except Exception:
errors.append(SimfileError(f"chart {c} timed_notes"))
return errors
def scan_directory(path: str, simfile_errors: Dict[str, List[SimfileError]]):
stats = Counter()
for entry in os.scandir(path):
if simfile_errors.get(entry.path) == []:
stats["skipped"] += 1
continue
if entry.is_dir():
stats.update(scan_directory(entry.path, simfile_errors))
elif any(entry.name.endswith(ext) for ext in (".sm", ".ssc")):
errors = check_simfile(entry.path)
stats["checked"] += 1
simfile_errors[entry.path] = errors
if errors:
stats["error"] += 1
pprint.pprint({"path": entry.path, "errors": errors})
else:
stats["success"] += 1
return stats
def dir_path(string):
if os.path.isdir(string):
return string
else:
raise ValueError("dir_path: not a directory")
def main():
argparser = argparse.ArgumentParser()
argparser.add_argument(
"directory",
help="directory of simfiles to scan",
type=dir_path,
)
argparser.add_argument(
"-s",
"--shelf",
help="shelf file to use",
default=f"shelf-{simfile.__version__}",
)
args = argparser.parse_args()
with shelve.open(args.shelf) as simfile_errors:
stats = scan_directory(args.directory, simfile_errors)
for k, v in stats.items():
print(k, v)
if __name__ == "__main__":
main()