示例#1
0
def kolejka_task(task_dir,
                 tests,
                 solution,
                 judgepy,
                 exist_ok=False,
                 debug=False):

    kolejka_image = None
    kolejka_requires = set()
    kolejka_exclusive = False
    kolejka_collects = dict()
    kolejka_stdout = 'console_stdout.txt'
    kolejka_stderr = 'console_stderr.txt'
    kolejka_limits = {}

    kolejka_system = '--observer'

    for test_id, test in tests.items():
        kolejka_opts = test.get('kolejka', dict())

        if 'image' in kolejka_opts:
            if kolejka_image and kolejka_image != kolejka_opts['image']:
                raise ValueError
            kolejka_image = kolejka_opts['image']
        for req in kolejka_opts.get('requires', []):
            kolejka_requires.add(req)
        kolejka_exclusive = kolejka_exclusive or bool(
            kolejka_opts.get('exclusive', False))
        kolejka_collects[test_id] = kolejka_opts.get('collect', [])
        kolejka_collects[test_id].append(config.SATORI_RESULT + '/**')
        test_limits = kolejka_opts.get('limits', {})
        if 'time' in test_limits:
            kolejka_limits['time'] = kolejka_limits.get(
                'time', datetime.timedelta(seconds=1)) + parse_time(
                    test_limits['time'])
        if 'memory' in test_limits:
            kolejka_limits['memory'] = max(kolejka_limits.get('memory', 0),
                                           parse_memory(test_limits['memory']))
        if 'swap' in test_limits:
            kolejka_limits['swap'] = max(kolejka_limits.get('swap', 0),
                                         parse_memory(test_limits['swap']))
        if 'cpus' in test_limits:
            kolejka_limits['cpus'] = max(kolejka_limits.get('cpus', 1),
                                         int(test_limits['cpus']))
        if 'network' in test_limits:
            kolejka_limits['network'] = kolejka_limits.get(
                'network', False) or bool(test_limits['network'])
        if 'pids' in test_limits:
            kolejka_limits['pids'] = max(kolejka_limits.get('pids', 16),
                                         int(test_limits['pids']))
        if 'storage' in test_limits:
            kolejka_limits['storage'] = kolejka_limits.get(
                'storage', 0) + parse_memory(test_limits['storage'])
        if 'workspace' in test_limits:
            kolejka_limits['workspace'] = kolejka_limits.get(
                'workspace', 0) + parse_memory(test_limits['workspace'])

    kolejka_image = kolejka_image or 'kolejka/satori:judge'

    from kolejka.common import KolejkaTask, KolejkaLimits
    task_dir = pathlib.Path(task_dir).resolve()
    solution = pathlib.Path(solution).resolve()
    judgepy = pathlib.Path(judgepy).resolve()

    task_dir.mkdir(parents=True, exist_ok=exist_ok)
    test_dir = pathlib.PurePath('tests')
    (task_dir / test_dir).mkdir()
    solution_dir = pathlib.PurePath('solution')
    (task_dir / solution_dir).mkdir()
    results_dir = pathlib.PurePath('results')
    results_yaml = pathlib.PurePath('results.yaml')

    kolejka_collect = []
    kolejka_collect += [{'glob': str(results_dir / results_yaml)}]
    for test_id, collects in kolejka_collects.items():
        for collect in collects:
            kolejka_collect += [{
                'glob':
                str(results_dir / str(test_id) / str(collect))
            }]
    if debug:
        kolejka_collect += [
            {
                'glob': str(test_dir) + '/**'
            },
            {
                'glob': str(solution_dir) + '/**'
            },
            {
                'glob': str(results_dir) + '/**'
            },
        ]

    tests_yaml = test_dir / 'tests.yaml'
    solution_path = solution_dir / solution.name
    (task_dir / solution_path).symlink_to(solution)
    judgepy_path = pathlib.PurePath('judge.py')
    (task_dir / judgepy_path).symlink_to(judgepy)
    lib_path = pathlib.PurePath(config.DISTRIBUTION_PATH)
    (task_dir / lib_path).symlink_to(judgepy.parent / lib_path)
    if not (judgepy.parent / lib_path).is_file():
        logging.warning(
            'Kolejka Judge library not present in {}. Try running library update.'
            .format(judgepy.parent / lib_path))

    task_args = [
        'python3',
        str(judgepy_path),
    ]
    if debug:
        task_args += [
            '--debug',
        ]
    task_args += [
        'execute',
        kolejka_system,
        str(tests_yaml),
        str(solution_path),
        str(results_dir),
        '--results',
        str(results_yaml),
    ]

    input_map = dict()

    class collect:
        def __init__(self, input_map):
            self.input_count = 0
            self.input_map = input_map

        def __call__(self, a):
            if isinstance(a, InputPath):
                a = pathlib.Path(a.path)
            if isinstance(a, pathlib.Path):
                if a in self.input_map:
                    return self.input_map[a]
                self.input_count += 1
                input_path = task_dir / test_dir / (
                    '%03d' % (self.input_count, )) / a.name
                input_path.parent.mkdir(exist_ok=True, parents=True)
                input_path.symlink_to(a)
                input_path = input_path.relative_to(task_dir)
                self.input_map[a] = input_path
                return input_path
            if isinstance(a, list):
                return [self(e) for e in a]
            if isinstance(a, dict):
                return dict([(self(k), self(v)) for k, v in a.items()])
            return a

    tests = collect(input_map)(tests)
    ctxyaml_dump(tests, task_dir / tests_yaml, work_dir=task_dir)

    task = KolejkaTask(
        str(task_dir),
        image=kolejka_image,
        requires=list(kolejka_requires),
        exclusive=kolejka_exclusive,
        limits=kolejka_limits,
        args=task_args,
        stdout=kolejka_stdout,
        stderr=kolejka_stderr,
        files=dict([(str(p), None) for p in [
            tests_yaml,
            solution_path,
            judgepy_path,
            lib_path,
        ] + list(input_map.values())]),
        collect=kolejka_collect,
    )
    task.commit()
示例#2
0
 def update_real_time(self, real_time):
     self._real_time = max(self._real_time, parse_time(real_time or '0s'))
示例#3
0
 def update_cpu_time(self, cpu_time):
     self._cpu_time = max(self._cpu_time, parse_time(cpu_time or '0s'))
示例#4
0
 def set_real_time(self, real_time):
     self._real_time = parse_time(real_time or '0s')
示例#5
0
 def set_cpu_time(self, cpu_time):
     self._cpu_time = parse_time(cpu_time or '0s')