Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add function for validating test names #114

Merged
merged 8 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/sinol_make/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

from sinol_make import util, oiejq

__version__ = "1.5.6"

__version__ = "1.5.7"


def configure_parsers():
parser = argparse.ArgumentParser(
Expand Down
5 changes: 3 additions & 2 deletions src/sinol_make/commands/export/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def get_generated_tests(self):
util.exit_with_error('Failed to run ingen.')

tests = glob.glob(os.path.join(working_dir, f'{self.task_id}*.in'))
return [package_util.extract_test_id(test) for test in tests]
return [package_util.extract_test_id(test, self.task_id) for test in tests]

def copy_package_required_files(self, target_dir: str):
"""
Expand Down Expand Up @@ -74,7 +74,7 @@ def copy_package_required_files(self, target_dir: str):
tests_to_copy = []
for ext in ['in', 'out']:
for test in glob.glob(os.path.join(os.getcwd(), ext, f'{self.task_id}*.{ext}')):
if package_util.extract_test_id(test) not in generated_tests:
if package_util.extract_test_id(test, self.task_id) not in generated_tests:
tests_to_copy.append(test)

if len(tests_to_copy) > 0:
Expand Down Expand Up @@ -132,6 +132,7 @@ def run(self, args: argparse.Namespace):

self.args = args
self.task_id = package_util.get_task_id()
package_util.validate_test_names(self.task_id)

with open(os.path.join(os.getcwd(), 'config.yml'), 'r') as config_file:
config = yaml.load(config_file, Loader=yaml.FullLoader)
Expand Down
1 change: 1 addition & 0 deletions src/sinol_make/commands/gen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def run(self, args: argparse.Namespace):

self.args = args
self.task_id = package_util.get_task_id()
package_util.validate_test_names(self.task_id)
self.ingen = gen_util.get_ingen(self.task_id, args.ingen_path)
print(util.info(f'Using ingen file {os.path.basename(self.ingen)}'))

Expand Down
13 changes: 5 additions & 8 deletions src/sinol_make/commands/gen/gen_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ def ingen_exists(task_id):
:param task_id: task id, for example abc
:return: True if exists, False otherwise
"""
return len(glob.glob(os.path.join(os.getcwd(), 'prog', task_id + 'ingen.*'))) > 0
return package_util.any_files_matching_pattern(task_id, f'{task_id}ingen.*')


def get_ingen(task_id=None, ingen_path=None):
def get_ingen(task_id, ingen_path=None):
"""
Find ingen source file in `prog/` directory.
If `ingen_path` is specified, then it will be used (if exists).
:param task_id: task id, for example abc. If None, then
will return any ingen matching "*ingen.*"
:param task_id: task id, for example abc.
:param ingen_path: path to ingen source file
:return: path to ingen source file or None if not found
"""
Expand All @@ -35,9 +34,7 @@ def get_ingen(task_id=None, ingen_path=None):
else:
util.exit_with_error(f'Ingen source file {ingen_path} does not exist.')

if task_id is None:
task_id = '*'
ingen = glob.glob(os.path.join(os.getcwd(), 'prog', task_id + 'ingen.*'))
ingen = package_util.get_files_matching_pattern(task_id, f'{task_id}ingen.*')
if len(ingen) == 0:
util.exit_with_error(f'Ingen source file for task {task_id} does not exist.')

Expand Down Expand Up @@ -78,7 +75,7 @@ def get_correct_solution(task_id):
:param task_id: task id, for example abc
:return: path to correct solution or None if not found
"""
correct_solution = glob.glob(os.path.join(os.getcwd(), 'prog', task_id + '.*'))
correct_solution = package_util.get_files_matching_pattern(task_id, f'{task_id}.*')
if len(correct_solution) == 0:
util.exit_with_error(f'Correct solution for task {task_id} does not exist.')
return correct_solution[0]
Expand Down
5 changes: 3 additions & 2 deletions src/sinol_make/commands/inwer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def verify_and_print_table(self) -> Dict[str, TestResult]:
sorted_tests = sorted(self.tests, key=lambda x: x[0])
executions: List[InwerExecution] = []
for test in sorted_tests:
results[test] = TestResult(test)
results[test] = TestResult(test, self.task_id)
executions.append(InwerExecution(test, results[test].test_name, self.inwer_executable))

has_terminal, terminal_width, terminal_height = util.get_terminal_size()
Expand Down Expand Up @@ -123,6 +123,7 @@ def run(self, args: argparse.Namespace):
util.exit_if_not_package()

self.task_id = package_util.get_task_id()
package_util.validate_test_names(self.task_id)
self.inwer = inwer_util.get_inwer_path(self.task_id, args.inwer_path)
if self.inwer is None:
if args.inwer_path is None:
Expand All @@ -133,7 +134,7 @@ def run(self, args: argparse.Namespace):
print(f'Verifying with inwer {util.bold(relative_path)}')

self.cpus = args.cpus or mp.cpu_count()
self.tests = package_util.get_tests(args.tests)
self.tests = package_util.get_tests(self.task_id, args.tests)

if len(self.tests) == 0:
util.exit_with_error('No tests found.')
Expand Down
2 changes: 1 addition & 1 deletion src/sinol_make/commands/inwer/inwer_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def get_inwer_path(task_id: str, path = None) -> Union[str, None]:
Returns path to inwer executable for given task or None if no inwer was found.
"""
if path is None:
inwers = glob.glob(os.path.join(os.getcwd(), 'prog', f'{task_id}inwer.*'))
inwers = package_util.get_files_matching_pattern(task_id, f'{task_id}inwer.*')
if len(inwers) == 0:
return None
return inwers[0]
Expand Down
4 changes: 2 additions & 2 deletions src/sinol_make/commands/inwer/structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ class TestResult:
valid: bool
output: str

def __init__(self, test_path):
def __init__(self, test_path, task_id):
self.test_path = test_path
self.test_name = os.path.split(test_path)[-1]
self.test_group = str(package_util.get_group(self.test_path))
self.test_group = str(package_util.get_group(self.test_path, task_id))

self.verified = False
self.valid = False
Expand Down
67 changes: 35 additions & 32 deletions src/sinol_make/commands/run/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def update_group_status(group_status, new_status):
return group_status


def print_view(term_width, term_height, program_groups_scores, all_results, print_data: PrintData, names, executions,
def print_view(term_width, term_height, task_id, program_groups_scores, all_results, print_data: PrintData, names, executions,
groups, scores, tests, possible_score, cpus, hide_memory, config, contest, args):
width = term_width - 13 # First column has 6 characters, the " | " separator has 3 characters and 4 for margin
programs_in_row = width // 13 # Each program has 10 characters and the " | " separator has 3 characters
Expand All @@ -79,7 +79,7 @@ def print_view(term_width, term_height, program_groups_scores, all_results, prin
for solution in names:
lang = package_util.get_file_lang(solution)
for test in tests:
time_sum += package_util.get_time_limit(test, config, lang, args)
time_sum += package_util.get_time_limit(test, config, lang, task_id, args)

time_remaining = (len(executions) - print_data.i - 1) * 2 * time_sum / cpus / 1000.0
title = 'Done %4d/%4d. Time remaining (in the worst case): %5d seconds.' \
Expand Down Expand Up @@ -122,17 +122,17 @@ def print_table_end():
if results[test].Time is not None:
if program_times[program][0] < results[test].Time:
program_times[program] = (results[test].Time, package_util.get_time_limit(test, config,
lang, args))
lang, task_id, args))
elif status == Status.TL:
program_times[program] = (2 * package_util.get_time_limit(test, config, lang, args),
package_util.get_time_limit(test, config, lang, args))
program_times[program] = (2 * package_util.get_time_limit(test, config, lang, task_id, args),
package_util.get_time_limit(test, config, lang, task_id, args))
if results[test].Memory is not None:
if program_memory[program][0] < results[test].Memory:
program_memory[program] = (results[test].Memory, package_util.get_memory_limit(test, config,
lang, args))
lang, task_id, args))
elif status == Status.ML:
program_memory[program] = (2 * package_util.get_memory_limit(test, config, lang, args),
package_util.get_memory_limit(test, config, lang, args))
program_memory[program] = (2 * package_util.get_memory_limit(test, config, lang, task_id, args),
package_util.get_memory_limit(test, config, lang, task_id, args))
if status == Status.PENDING:
group_status = Status.PENDING
else:
Expand Down Expand Up @@ -187,29 +187,29 @@ def print_group_seperator():

last_group = None
for test in tests:
group = package_util.get_group(test)
group = package_util.get_group(test, task_id)
if last_group != group:
if last_group is not None:
print_group_seperator()
last_group = group

print(margin + "%6s" % package_util.extract_test_id(test), end=" | ")
print(margin + "%6s" % package_util.extract_test_id(test, task_id), end=" | ")
for program in program_group:
lang = package_util.get_file_lang(program)
result = all_results[program][package_util.get_group(test)][test]
result = all_results[program][package_util.get_group(test, task_id)][test]
status = result.Status
if status == Status.PENDING: print(10 * ' ', end=" | ")
else:
print("%3s" % colorize_status(status),
("%17s" % color_time(result.Time, package_util.get_time_limit(test, config, lang, args)))
("%17s" % color_time(result.Time, package_util.get_time_limit(test, config, lang, task_id, args)))
if result.Time is not None else 7*" ", end=" | ")
print()
if not hide_memory:
print(8*" ", end=" | ")
for program in program_group:
lang = package_util.get_file_lang(program)
result = all_results[program][package_util.get_group(test)][test]
print(("%20s" % color_memory(result.Memory, package_util.get_memory_limit(test, config, lang, args)))
result = all_results[program][package_util.get_group(test, task_id)][test]
print(("%20s" % color_memory(result.Memory, package_util.get_memory_limit(test, config, lang, task_id, args)))
if result.Memory is not None else 10*" ", end=" | ")
print()

Expand Down Expand Up @@ -277,9 +277,9 @@ def extract_file_name(self, file_path):


def get_group(self, test_path):
if package_util.extract_test_id(test_path).endswith("ocen"):
if package_util.extract_test_id(test_path, self.ID).endswith("ocen"):
return 0
return int("".join(filter(str.isdigit, package_util.extract_test_id(test_path))))
return int("".join(filter(str.isdigit, package_util.extract_test_id(test_path, self.ID))))


def get_executable_key(self, executable):
Expand Down Expand Up @@ -604,7 +604,7 @@ def run_solution(self, data_for_execution: ExecutionData):
"""

(name, executable, test, time_limit, memory_limit, timetool_path) = data_for_execution
file_no_ext = paths.get_executions_path(name, package_util.extract_test_id(test))
file_no_ext = paths.get_executions_path(name, package_util.extract_test_id(test, self.ID))
output_file = file_no_ext + ".out"
result_file = file_no_ext + ".res"
hard_time_limit_in_s = math.ceil(2 * time_limit / 1000.0)
Expand Down Expand Up @@ -640,8 +640,10 @@ def run_solutions(self, compiled_commands, names, solutions):
lang = package_util.get_file_lang(name)
if result:
for test in self.tests:
executions.append((name, executable, test, package_util.get_time_limit(test, self.config, lang, self.args),
package_util.get_memory_limit(test, self.config, lang, self.args), self.timetool_path))
executions.append((name, executable, test,
package_util.get_time_limit(test, self.config, lang, self.ID, self.args),
package_util.get_memory_limit(test, self.config, lang, self.ID, self.args),
self.timetool_path))
all_results[name][self.get_group(test)][test] = ExecutionResult(Status.PENDING)
os.makedirs(paths.get_executions_path(name), exist_ok=True)
else:
Expand All @@ -658,8 +660,8 @@ def run_solutions(self, compiled_commands, names, solutions):
run_event = threading.Event()
run_event.set()
thr = threading.Thread(target=printer.printer_thread,
args=(run_event, print_view, program_groups_scores, all_results, print_data, names,
executions, self.groups, self.scores, self.tests, self.possible_score,
args=(run_event, print_view, self.ID, program_groups_scores, all_results, print_data,
names, executions, self.groups, self.scores, self.tests, self.possible_score,
self.cpus, self.args.hide_memory, self.config, self.contest, self.args))
thr.start()

Expand All @@ -681,7 +683,7 @@ def run_solutions(self, compiled_commands, names, solutions):
run_event.clear()
thr.join()

print("\n".join(print_view(terminal_width, terminal_height, program_groups_scores, all_results, print_data,
print("\n".join(print_view(terminal_width, terminal_height, self.ID, program_groups_scores, all_results, print_data,
names, executions, self.groups, self.scores, self.tests, self.possible_score,
self.cpus, self.args.hide_memory, self.config, self.contest, self.args)[0]))

Expand Down Expand Up @@ -738,15 +740,15 @@ def get_whole_groups(self):
Returns a list of groups for which all tests were run.
"""
group_sizes = {}
for test in package_util.get_tests():
group = package_util.get_group(test)
for test in package_util.get_tests(self.ID):
group = package_util.get_group(test, self.ID)
if group not in group_sizes:
group_sizes[group] = 0
group_sizes[group] += 1

run_group_sizes = {}
for test in self.tests:
group = package_util.get_group(test)
group = package_util.get_group(test, self.ID)
if group not in run_group_sizes:
run_group_sizes[group] = 0
run_group_sizes[group] += 1
Expand Down Expand Up @@ -1027,7 +1029,7 @@ def exit(self):
cnt=len(self.failed_compilations), letter='' if len(self.failed_compilations) == 1 else 's'))

def set_scores(self):
self.tests = package_util.get_tests(self.args.tests)
self.tests = package_util.get_tests(self.ID, self.args.tests)
self.groups = self.get_groups(self.tests)
self.scores = collections.defaultdict(int)

Expand Down Expand Up @@ -1071,10 +1073,10 @@ def get_valid_input_files(self):
Returns list of input files that have corresponding output file.
"""
output_tests = glob.glob(os.path.join(os.getcwd(), "out", "*.out"))
output_tests_ids = [package_util.extract_test_id(test) for test in output_tests]
output_tests_ids = [package_util.extract_test_id(test, self.ID) for test in output_tests]
valid_input_files = []
for test in self.tests:
if package_util.extract_test_id(test) in output_tests_ids:
if package_util.extract_test_id(test, self.ID) in output_tests_ids:
valid_input_files.append(test)
return valid_input_files

Expand Down Expand Up @@ -1129,6 +1131,7 @@ def run(self, args):
util.exit_if_not_package()

self.set_constants()
package_util.validate_test_names(self.ID)
self.args = args
with open(os.path.join(os.getcwd(), "config.yml"), 'r') as config:
try:
Expand All @@ -1150,7 +1153,7 @@ def run(self, args):
print("Task: %s (tag: %s)" % (title, self.ID))
self.cpus = args.cpus or mp.cpu_count()

checker = glob.glob(os.path.join(os.getcwd(), "prog", f'{self.ID}chk.*'))
checker = package_util.get_files_matching_pattern(self.ID, f'{self.ID}chk.*')
if len(checker) != 0:
print(util.info("Checker found: %s" % os.path.basename(checker[0])))
self.checker = checker[0]
Expand All @@ -1163,7 +1166,7 @@ def run(self, args):
else:
self.checker = None

lib = glob.glob(os.path.join(os.getcwd(), "prog", f'{self.ID}lib.*'))
lib = package_util.get_files_matching_pattern(self.ID, f'{self.ID}lib.*')
self.has_lib = len(lib) != 0

self.set_scores()
Expand All @@ -1176,8 +1179,8 @@ def run(self, args):
lang = package_util.get_file_lang(solution)
for test in self.tests:
# The functions will exit if the limits are not set
_ = package_util.get_time_limit(test, self.config, lang, self.args)
_ = package_util.get_memory_limit(test, self.config, lang, self.args)
_ = package_util.get_time_limit(test, self.config, lang, self.ID, self.args)
_ = package_util.get_memory_limit(test, self.config, lang, self.ID, self.args)

results, all_results = self.compile_and_run(solutions)
self.check_errors(all_results)
Expand Down
Loading