diff options
Diffstat (limited to 'kpov_judge/test_task.py')
-rwxr-xr-x | kpov_judge/test_task.py | 246 |
1 files changed, 0 insertions, 246 deletions
diff --git a/kpov_judge/test_task.py b/kpov_judge/test_task.py deleted file mode 100755 index 43aaf38..0000000 --- a/kpov_judge/test_task.py +++ /dev/null @@ -1,246 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import collections -import getpass -import inspect -import io -import json -import locale -import os -import random -import readline -import sys -import urllib.request - -import yaml -import kpov_util - -locale.setlocale(locale.LC_ALL, ['C', 'utf8']) -readline.set_completer_delims(readline.get_completer_delims().replace('/', '')) -readline.parse_and_bind('tab: complete') - -TASK_URL = "file://" + os.getcwd() + '/tasks' -PARAMS_FILE = os.path.expanduser("~/.kpov_params.yaml") -DEFAULT_LANGUAGE = 'si' - -def print_header(title, spacing=1): - print('\n'*spacing + '> {}'.format(title)) - -# get the parameters for a task either from the user or from a file -def get_params(params, params_meta, language=None): - # prefill input() prompt with given text - def rlinput(prompt, prefill=''): - readline.set_startup_hook(lambda: readline.insert_text(prefill)) - try: - return input(prompt) - finally: - readline.set_startup_hook() - - if language is None: - language = params.get('language', DEFAULT_LANGUAGE) - - # print all non-writable parameters first, then prompt for writable ones - for name, meta in sorted(params_meta.items(), key=lambda n: n[1].get('w', True)): - description = meta.get('descriptions', {}).get(language, name) - if name not in params: - params[name] = None - if meta.get('w', True): - try: - if meta.get('masked', False): - s = getpass.getpass('{}: '.format(description)) - else: - s = rlinput('{}: '.format(description), params.get(name, '')) - if s: - params[name] = s - except EOFError: - print() - else: - print('{}: {}'.format(name, params.get(name, ''))) - return params - -def add_meta_to_argparser(argparser, meta, defaults={}): - language = defaults.get('language', DEFAULT_LANGUAGE) - for k, v in meta.items(): - try: - desc = v['descriptions'][language].encode("utf-8") - except: - desc = k - argparser.add_argument('--'+k, nargs='?', type=str, help=desc, - default=defaults.get(k, None)) - -def load_params(filename): - try: - return yaml.load(open(filename)) - except: - return {} - -def locate_task(params, argparser, quiet=False): - # first the URL where all tasks are stored - url_meta = { - 'task_url': {'descriptions': {'si': 'URL z nalogami', 'en': 'Root URL for all tasks'}} - } - if 'task_url' not in params: - params['task_url'] = TASK_URL - add_meta_to_argparser(argparser, meta=url_meta, defaults=params) - args, unknown_args = argparser.parse_known_args() - params['task_url'] = args.task_url - if not quiet: - print_header('Task', spacing=0) - params = get_params(params, url_meta) - - # and finally, the name of the task - fetch_params_meta = collections.OrderedDict({'task_name': {'descriptions': {'si': 'Ime naloge', 'en': 'Task name'}}}) - add_meta_to_argparser(argparser, meta=fetch_params_meta, defaults=params) - args, unknown_args = argparser.parse_known_args() - # update params with the now known args - for k, v in fetch_params_meta.items(): - params[k] = vars(args).get(k, params.get(k, None)) - if not quiet: - params = get_params(params, fetch_params_meta) - return params - -def http_auth(url, username, password): - password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm() - password_mgr.add_password(None, url, username, password) - handler = urllib.request.HTTPBasicAuthHandler(password_mgr) - opener = urllib.request.build_opener(handler) - urllib.request.install_opener(opener) # now all calls to urlopen use our opener - -def load_task(stream): - # the stream should definitions for the functions task(…), - # task_check and gen_params, and a dictionary params_meta - d = {} - exec(compile(source, 'task.py', 'exec'), globals(), d) - return d['task'], d['task_check'], d['params_meta'], d['gen_params'] - - -if __name__ == '__main__': - # get the parameters needed to get to the task, such as the URLs, the name of the task and optionally an ID from the student - # start with the the parameters needed for the dialog gui to work - argparser = argparse.ArgumentParser(conflict_handler='resolve', - description='Test a KPOV Judge task.') - argparser.add_argument('-h', '--help', action='store_true') - argparser.add_argument('-q', '--quiet', action='store_true', - help='disable prompts') - argparser.add_argument('-g', '--generate_params', action='store_true', - help='generate initial values for the task parameters') - argparser.add_argument('-pf', '--params_file', nargs='?', default=PARAMS_FILE, - help='a local file with saved param values') - basic_args, unknown_args = argparser.parse_known_args() - - # get default parameters including language - params = load_params(basic_args.params_file) - argparser.add_argument('-l', '--language', nargs='?', - default=params.get('language', DEFAULT_LANGUAGE), - help='the language used') - basic_args, unknown_args = argparser.parse_known_args() - params['language'] = basic_args.language - - if basic_args.help: - argparser.print_help() - exit(0) - - # continue with the parameters needed to get the task - params = locate_task(params, argparser, quiet=basic_args.quiet) - # TODO: if the task name is missing or invalid, try to get a list of tasks - # get task source and generate params if neccessarry - try: - task_url = params['task_url'] - task_name = params['task_name'] - - source = urllib.request.urlopen("{task_url}/{task_name}/task.py".format(**params)).read() - if not source: - raise Exception('no such task: {}'.format(task_name)) - task, task_check, task_params_meta, gen_params = load_task(source) - except Exception as e: - print(e) - with open(basic_args.params_file, 'w') as f: - yaml.dump(params, f) - exit(1) - - # get stored task parameters - params['task_params'] = params.get('task_params', {}) - task_params = params['task_params'].setdefault(task_name, {}) - tokens = params.setdefault('tokens', {}) - - # ensure we have a submission token - if task_url.startswith('http'): - n_tries = 3 - while n_tries > 0: - try: - if tokens.get(task_name): - response = urllib.request.urlopen( - '{task_url}/{task_name}/params.json'.format(**params), - data=urllib.parse.urlencode({'token': tokens.get(task_name)}).encode()) - response = json.load(io.TextIOWrapper(response)) - if response: - # got params - task_params.update(response) - break - else: - # did not get a token, try again with password - del tokens[task_name] - n_tries -= 1 - - if not tokens.get(task_name): - # get the student's ID and password - # TODO clunky, should refactor all argument-getting stuff - user_meta = collections.OrderedDict(( - ('username', {'descriptions': {'si': 'Uporabniško ime', 'en': 'Username'}}), - ('password', {'descriptions': {'si': 'Geslo', 'en': 'Password'}, 'masked': True}), - )) - print_header('KPOV login') - user_params = get_params(params, user_meta, params['language']) - - http_auth(task_url, user_params['username'], user_params['password']) - response = urllib.request.urlopen('{task_url}/{task_name}/token.json'.format(**params)) - response = json.load(io.TextIOWrapper(response)) - if response: - tokens[task_name] = response['token'] - params['username'] = user_params['username'] - except Exception as ex: - print(ex) - - if basic_args.generate_params: - #prejema lahko samo stringe in ne številk (potrebno je str(int) - # print ("params before: {} {}".format(params, task_params)) - task_params.update(gen_params(params['username'], task_params_meta)) - # print ("params after: {} {}".format(params, task_params)) - - task_argparser = argparse.ArgumentParser(parents=[argparser], conflict_handler='resolve', add_help=True) - add_meta_to_argparser(task_argparser, task_params_meta, defaults=task_params) - args = vars(task_argparser.parse_args()) - for k in task_params_meta: - if args.get(k): - task_params[k] = args[k] - if not basic_args.quiet: - print_header('Task parameters') - task_params = get_params(task_params, task_params_meta, language=params['language']) - - public_params = {} - for k in inspect.getargs(task.__code__)[0]: - public_params[k] = task_params[k] - params['task_params'][params['task_name']] = task_params - - # save parameters for the next run - with open(basic_args.params_file, 'w') as f: - yaml.dump(params, f) - - try: - print_header('Results', spacing=0 if basic_args.quiet else 1) - print('Running task... ', end='', flush=True) - task_result = task(**public_params) - print('checking task... ', end='', flush=True) - task_params['token'] = tokens[task_name] # hack to avoid changing task_check signature - score, hints = task_check(task_result, task_params) - del task_params['token'] - print('done!') - print('Score: {}'.format(score)) - - print_header('Hints') - for hint in hints: - print(hint.strip()) - except Exception as e: - import traceback - traceback.print_exc() |