diff --git a/cmscontrib/gerpythonformat/Executable.py b/cmscontrib/gerpythonformat/Executable.py index 0b02a71c79..ee1634a8ab 100644 --- a/cmscontrib/gerpythonformat/Executable.py +++ b/cmscontrib/gerpythonformat/Executable.py @@ -3,7 +3,7 @@ # Programming contest management system # Copyright © 2013-2017 Tobias Lenz -# Copyright © 2013-2014 Fabian Gundlach <320pointsguy@gmail.com> +# Copyright © 2013-2022 Fabian Gundlach <320pointsguy@gmail.com> # Copyright © 2022 Manuel Gundlach # # This program is free software: you can redistribute it and/or modify @@ -194,9 +194,9 @@ def __call__(self, *args, **kwargs): stderr = kwargs.pop("stderr", None) dependencies = kwargs.pop("dependencies", []) - self.run(args, kwargs, stdin=stdin, stdinstring=stdinstring, - stdout=stdout, stderr=stderr, - dependencies=dependencies) + return self.run(args, kwargs, stdin=stdin, stdinstring=stdinstring, + stdout=stdout, stderr=stderr, + dependencies=dependencies) class ParamsExecutable(Executable): @@ -244,9 +244,9 @@ def run(self, args, kwargs, stdin=None, stdinstring=None, stdout=None, stdin = self.stdin if stdinstring is None: stdinstring = self.stdinstring - self.parent.run(args + self.args, k, stdin=stdin, - stdinstring=stdinstring, stdout=stdout, - stderr=stderr, dependencies=dependencies) + return self.parent.run(args + self.args, k, stdin=stdin, + stdinstring=stdinstring, stdout=stdout, + stderr=stderr, dependencies=dependencies) def __str__(self): return "{} with additional arguments {}" \ @@ -377,6 +377,7 @@ def run(self, args, kwargs, stdin=None, stdinstring=None, stdout=None, "Error executing program {} with parameters {}" .format(self.conf.short_path(self.wanted_path()), str(list(args) + keyword_list(kwargs)))) + return r def __str__(self): return self.conf.short_path(self.executable) diff --git a/cmscontrib/gerpythonformat/TaskConfig.py b/cmscontrib/gerpythonformat/TaskConfig.py index 7fd6b0fed1..f1d50c768d 100644 --- a/cmscontrib/gerpythonformat/TaskConfig.py +++ b/cmscontrib/gerpythonformat/TaskConfig.py @@ -3,7 +3,7 @@ # Programming contest management system # Copyright © 2013-2022 Tobias Lenz -# Copyright © 2013-2016 Fabian Gundlach <320pointsguy@gmail.com> +# Copyright © 2013-2022 Fabian Gundlach <320pointsguy@gmail.com> # Copyright © 2022 Manuel Gundlach # # This program is free software: you can redistribute it and/or modify @@ -28,7 +28,7 @@ remaining_line_length, indent, IndentManager from cmscontrib.gerpythonformat.CommonConfig import exported_function, CommonConfig from cmscontrib.gerpythonformat.Executable import ExitCodeException, \ - InternalPython + InternalPython, CPPProgram from cmscontrib.gerpythonformat.ConstraintParser import ConstraintList, \ merge_constraints, read_frequency, check_bounds from cmscommon.constants import SCORE_MODE_MAX_TOKENED_LAST, \ @@ -1471,6 +1471,8 @@ def checker(self, *args, **kwargs): """ Register a test case checker for the "current" task, subtask or group. + The checker must be a CPPProgram. + See :py:meth:`.Scope.add_checker`. """ @@ -1574,15 +1576,15 @@ def _check(self, checker, infile, outfile, caseno, check_counter): if self.minimal: return - try: - checker_log = "checker-log.txt" + if not isinstance(checker, CPPProgram): + raise Exception("Only checkers written in C++ are allowed.") - checker(outfile, stdout=checker_log, stdin=infile, - dependencies=[outfile]) + try: + result = checker(outfile, stdin=infile, + dependencies=[outfile]) - with open(checker_log, 'r') as log_file: - log = log_file.read() - return json.loads(log) if len(log) > 0 else None + log = result.out + return json.loads(log) if len(log) > 0 else None except ExitCodeException: raise Exception( diff --git a/docs/External contest formats.rst b/docs/External contest formats.rst index a359007a6f..de6eb72000 100644 --- a/docs/External contest formats.rst +++ b/docs/External contest formats.rst @@ -331,6 +331,8 @@ To check if your test cases are all valid, you can specify test case checkers us In the above example, :samp:`checker OUTPUT 0 < INPUT` would be run for all test cases and :samp:`checker OUTPUT 1 < INPUT` would be run for the test cases belonging to subtask 1. +Checkers must be written in C++ and compiled with `compile(...)`. They mustn't write anything to stdout. On the other hand, stderr output is allowed and will be displayed to the user. + Constraints ^^^^^^^^^^^