88import json
99import logging
1010import os
11- import pkg_resources
1211import sys
12+ import tempfile
1313import time
1414from argparse import ArgumentParser
1515from collections import OrderedDict
1616from datetime import datetime
1717
1818import pebble
19+ import pkg_resources
1920from termcolor import colored
2021
2122from .models import default_user
@@ -81,17 +82,18 @@ def run_with_timeout(entry_point, timeout, progress, dt=0.1, **kwargs):
8182 # TODO : multi-process over the different tokens
8283 spinner = itertools .cycle (r"\|/-" )
8384 pool = pebble .ProcessPool (max_workers = 1 )
84- line = walltime = format_time (0 )
85+ line = elapsed = format_time (0 )
8586 with pool :
8687 t0 = time .time ()
8788 func = entry_point .load ()
8889 future = pool .schedule (func , kwargs = kwargs , timeout = timeout )
8990 while not future .done ():
90- line = "\r " + walltime + " " + progress + " " + next (spinner )
91- sys .stderr .write (line )
92- sys .stderr .flush ()
91+ if progress is not None :
92+ line = "\r " + elapsed + " " + progress + " " + next (spinner )
93+ sys .stderr .write (line )
94+ sys .stderr .flush ()
9395 time .sleep (dt )
94- walltime = format_time (time .time () - t0 )
96+ elapsed = format_time (time .time () - t0 , timeout )
9597 walltime = time .time () - t0
9698 try :
9799 a , b = future .result ()
@@ -100,8 +102,12 @@ def run_with_timeout(entry_point, timeout, progress, dt=0.1, **kwargs):
100102 crashed = True
101103 else :
102104 crashed = False
103- sys .stderr .write ("\r " + " " * len (line ) + "\r " )
104- sys .stderr .flush ()
105+ # longest correct answer seen so far has been 32 chars
106+ a = str (a )[:50 ]
107+ b = str (b )[:50 ]
108+ if progress is not None :
109+ sys .stderr .write ("\r " + " " * len (line ) + "\r " )
110+ sys .stderr .flush ()
105111 return a , b , walltime , crashed
106112
107113
@@ -116,6 +122,29 @@ def format_time(t, timeout=DEFAULT_TIMEOUT):
116122 return runtime
117123
118124
125+ def run_one (year , day , input_data , entry_point , timeout = DEFAULT_TIMEOUT , progress = None ):
126+ prev = os .getcwd ()
127+ scratch = tempfile .mkdtemp (prefix = "{}-{:02d}-" .format (year , day ))
128+ os .chdir (scratch )
129+ assert not os .path .exists ("input.txt" )
130+ try :
131+ with open ("input.txt" , "w" ) as f :
132+ f .write (input_data )
133+ a , b , walltime , crashed = run_with_timeout (
134+ entry_point = entry_point ,
135+ timeout = timeout ,
136+ year = year ,
137+ day = day ,
138+ data = input_data ,
139+ progress = progress ,
140+ )
141+ finally :
142+ os .unlink ("input.txt" )
143+ os .chdir (prev )
144+ os .rmdir (scratch )
145+ return a , b , walltime , crashed
146+
147+
119148def run_for (plugins , years , days , datasets , timeout = DEFAULT_TIMEOUT , autosubmit = True ):
120149 aoc_now = datetime .now (tz = AOC_TZ )
121150 all_entry_points = pkg_resources .iter_entry_points (group = "adventofcode.user" )
@@ -130,17 +159,20 @@ def run_for(plugins, years, days, datasets, timeout=DEFAULT_TIMEOUT, autosubmit=
130159 for year , day , plugin , dataset in it :
131160 if year == aoc_now .year and day > aoc_now .day :
132161 continue
133- os .environ ["AOC_SESSION" ] = datasets [dataset ]
162+ token = datasets [dataset ]
163+ entry_point = entry_points [plugin ]
164+ os .environ ["AOC_SESSION" ] = token
134165 puzzle = Puzzle (year = year , day = day )
135- progress = "{0.year}/{0.day:<2d} - {0.title:<40} {1:>%d}/{2:<%d}"
166+ title = puzzle .title
167+ progress = "{}/{:<2d} - {:<40} {:>%d}/{:<%d}"
136168 progress %= (userpad , datasetpad )
137- progress = progress .format (puzzle , plugin , dataset )
138- a , b , walltime , crashed = run_with_timeout (
139- entry_point = entry_points [plugin ],
169+ progress = progress .format (year , day , title , plugin , dataset )
170+ a , b , walltime , crashed = run_one (
171+ year = year ,
172+ day = day ,
173+ input_data = puzzle .input_data ,
174+ entry_point = entry_point ,
140175 timeout = timeout ,
141- year = puzzle .year ,
142- day = puzzle .day ,
143- data = puzzle .input_data ,
144176 progress = progress ,
145177 )
146178 runtime = format_time (walltime , timeout )
@@ -162,6 +194,8 @@ def run_for(plugins, years, days, datasets, timeout=DEFAULT_TIMEOUT, autosubmit=
162194 except AttributeError :
163195 pass
164196 correct = str (expected ) == answer
197+ if crashed :
198+ assert not correct
165199 icon = colored ("✔" , "green" ) if correct else colored ("✖" , "red" )
166200 correction = ""
167201 if not correct :
0 commit comments