Add option to run a build command for runners
This commit is contained in:
parent
f7eb29eb14
commit
d3387fba19
2 changed files with 60 additions and 27 deletions
80
aoc
80
aoc
|
@ -8,7 +8,7 @@ import sys
|
||||||
import json
|
import json
|
||||||
import subprocess
|
import subprocess
|
||||||
from io import BufferedReader
|
from io import BufferedReader
|
||||||
from typing import Optional
|
from typing import Optional, Callable
|
||||||
from glob import glob
|
from glob import glob
|
||||||
import time
|
import time
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
@ -17,8 +17,8 @@ from tqdm import tqdm
|
||||||
CHALLENGES_DIR = "challenges"
|
CHALLENGES_DIR = "challenges"
|
||||||
SAMPLE_TEST_JSON = "{}"
|
SAMPLE_TEST_JSON = "{}"
|
||||||
RUNNERS = {
|
RUNNERS = {
|
||||||
"py": ["./runners/py.sh"],
|
"py": (None, ["./runners/py.sh"]),
|
||||||
"go": ["go", "run"],
|
"go": (["./runners/buildGo.sh"], None),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,12 +76,13 @@ def time_command(args: list[str], stdin=None) -> tuple[int, float]:
|
||||||
return proc.returncode, dur
|
return proc.returncode, dur
|
||||||
|
|
||||||
|
|
||||||
def run_command(args: list[str], stdin=None) -> tuple[int, str]:
|
def run_command(args: list[str], stdin=None, cache=True) -> tuple[int, str]:
|
||||||
ah = hash("".join(args))
|
if cache:
|
||||||
sh = hash(stdin)
|
ah = hash("".join(args))
|
||||||
|
sh = hash(stdin)
|
||||||
|
|
||||||
if (ah, sh) in known_runs:
|
if (ah, sh) in known_runs:
|
||||||
return known_runs[(ah, sh)]
|
return known_runs[(ah, sh)]
|
||||||
|
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
|
|
||||||
|
@ -92,7 +93,8 @@ def run_command(args: list[str], stdin=None) -> tuple[int, str]:
|
||||||
|
|
||||||
proc = subprocess.run(args, stdout=subprocess.PIPE, **kwargs)
|
proc = subprocess.run(args, stdout=subprocess.PIPE, **kwargs)
|
||||||
|
|
||||||
known_runs[((ah, sh))] = (proc.returncode, proc.stdout)
|
if cache:
|
||||||
|
known_runs[((ah, sh))] = (proc.returncode, proc.stdout)
|
||||||
|
|
||||||
return proc.returncode, proc.stdout
|
return proc.returncode, proc.stdout
|
||||||
|
|
||||||
|
@ -143,6 +145,40 @@ def run_part(command: list[str], label: str, spec: dict[str, str | BufferedReade
|
||||||
print(formatted_result_str)
|
print(formatted_result_str)
|
||||||
|
|
||||||
|
|
||||||
|
def get_runner_command(file_name: str) -> tuple[list[str], Optional[Callable[[], None]]]:
|
||||||
|
"""
|
||||||
|
Builds a solution using `command` then returns a path to the executable.
|
||||||
|
"""
|
||||||
|
file_extension = file_name.split(".")[-1].lower()
|
||||||
|
|
||||||
|
if file_extension not in RUNNERS:
|
||||||
|
print("No compatible runner found", file=sys.stderr)
|
||||||
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
(runner_build, runner_run) = RUNNERS[file_extension]
|
||||||
|
|
||||||
|
if runner_build is None:
|
||||||
|
if runner_run is not None:
|
||||||
|
return runner_run + [file_name]
|
||||||
|
print(f"No build or run command specified for runner {file_extension}")
|
||||||
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
if runner_run is not None and runner_build is not None:
|
||||||
|
print(f"Build command and run command specified for {file_extension} - cannot determine path forwards.")
|
||||||
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
command = runner_build + [file_name]
|
||||||
|
set_terminal_colour("grey")
|
||||||
|
print("Building...", end="\r")
|
||||||
|
set_terminal_colour("reset")
|
||||||
|
exit_code, fpath = run_command(command, cache=False)
|
||||||
|
if exit_code != 0:
|
||||||
|
print(f"Failed to build: `{command}` returned exit code {exit_code}")
|
||||||
|
raise SystemExit(1)
|
||||||
|
fpstr = fpath.decode().strip()
|
||||||
|
return [fpstr], lambda: os.unlink(fpstr)
|
||||||
|
|
||||||
|
|
||||||
class CLI(object):
|
class CLI(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def init(year: int, day: int):
|
def init(year: int, day: int):
|
||||||
|
@ -229,28 +265,17 @@ class CLI(object):
|
||||||
if select_part:
|
if select_part:
|
||||||
select_part = str(select_part)
|
select_part = str(select_part)
|
||||||
|
|
||||||
# Stat file
|
|
||||||
# Get file extension
|
|
||||||
# Based on file extension, run
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
os.stat(fpath)
|
os.stat(fpath)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
print(f"Could not stat {fpath}", file=sys.stderr)
|
print(f"Could not stat {fpath}", file=sys.stderr)
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
|
|
||||||
file_extension = fpath.split(".")[-1].lower()
|
cmd, cleanup = get_runner_command(fpath)
|
||||||
|
|
||||||
if file_extension not in RUNNERS:
|
|
||||||
print("No compatible runner found", file=sys.stderr)
|
|
||||||
raise SystemExit(1)
|
|
||||||
|
|
||||||
challenge_dir = Path(os.path.dirname(fpath))
|
challenge_dir = Path(os.path.dirname(fpath))
|
||||||
input_file = open(challenge_dir / "input.txt", "rb")
|
input_file = open(challenge_dir / "input.txt", "rb")
|
||||||
|
|
||||||
cmd = RUNNERS[file_extension].copy()
|
|
||||||
cmd.append(fpath)
|
|
||||||
|
|
||||||
if test_only or not no_test:
|
if test_only or not no_test:
|
||||||
test_specs = json.load(open(challenge_dir / "tests.json"))
|
test_specs = json.load(open(challenge_dir / "tests.json"))
|
||||||
|
|
||||||
|
@ -269,6 +294,9 @@ class CLI(object):
|
||||||
|
|
||||||
input_file.close()
|
input_file.close()
|
||||||
|
|
||||||
|
if cleanup is not None:
|
||||||
|
cleanup()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def bench(fpath: str, n: int = 100):
|
def bench(fpath: str, n: int = 100):
|
||||||
try:
|
try:
|
||||||
|
@ -279,15 +307,10 @@ class CLI(object):
|
||||||
|
|
||||||
file_extension = fpath.split(".")[-1].lower()
|
file_extension = fpath.split(".")[-1].lower()
|
||||||
|
|
||||||
if file_extension not in RUNNERS:
|
|
||||||
print("No compatible runner found", file=sys.stderr)
|
|
||||||
raise SystemExit(1)
|
|
||||||
|
|
||||||
challenge_dir = Path(os.path.dirname(fpath))
|
challenge_dir = Path(os.path.dirname(fpath))
|
||||||
input_file = open(challenge_dir / "input.txt", "rb")
|
input_file = open(challenge_dir / "input.txt", "rb")
|
||||||
|
|
||||||
cmd = RUNNERS[file_extension].copy()
|
cmd, cleanup = get_runner_command(fpath)
|
||||||
cmd.append(fpath)
|
|
||||||
|
|
||||||
benchmark_file = Path(CHALLENGES_DIR) / challenge_dir.parts[1] / "benchmarks.jsonl"
|
benchmark_file = Path(CHALLENGES_DIR) / challenge_dir.parts[1] / "benchmarks.jsonl"
|
||||||
benchmark_fd = open(benchmark_file, "a")
|
benchmark_fd = open(benchmark_file, "a")
|
||||||
|
@ -315,6 +338,9 @@ class CLI(object):
|
||||||
benchmark_fd.close()
|
benchmark_fd.close()
|
||||||
input_file.close()
|
input_file.close()
|
||||||
|
|
||||||
|
if cleanup is not None:
|
||||||
|
cleanup()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def addtest(year: int, day: int, part: int, output: str):
|
def addtest(year: int, day: int, part: int, output: str):
|
||||||
"""
|
"""
|
||||||
|
|
7
runners/buildGo.sh
Normal file
7
runners/buildGo.sh
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
TEMPFILE=$(mktemp)
|
||||||
|
go build -o "$TEMPFILE" "$1"
|
||||||
|
echo $TEMPFILE
|
Loading…
Add table
Add a link
Reference in a new issue