From 86287e6a4fa07d03aa906965a182425320e445ce Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Thu, 27 Aug 2015 15:52:04 +0200 Subject: Replace prolog.engine.run with ask_all Creating and destroying the pengine should be handled somewhere else. This commit also removes query functionality from prolog.engine.create. --- monkey/monkey.py | 14 +++++----- prolog/engine.py | 66 +++++++++++++++--------------------------------- server/prolog_session.py | 6 ++--- 3 files changed, 32 insertions(+), 54 deletions(-) diff --git a/monkey/monkey.py b/monkey/monkey.py index 02048de..0939448 100755 --- a/monkey/monkey.py +++ b/monkey/monkey.py @@ -10,12 +10,14 @@ from .util import damerau_levenshtein, PQueue # Check whether all tests for problem [name] succeed. def test(name, code): - try: - reply, output = prolog.engine.create( - code=code, query='run_tests({})'.format(name)) - return reply.get('event') == 'success' - except Exception as ex: - return False + return False + # XXX currently broken + #try: + # reply, output = prolog.engine.create( + # code=code, query='run_tests({})'.format(name)) + # return reply.get('event') == 'success' + #except Exception as ex: + # return False # Starting from [code], find a sequence of edits that transforms it into a # correct predicate for [name]. Append [aux_code] when testing (available facts diff --git a/prolog/engine.py b/prolog/engine.py index dc117f0..f0d1157 100644 --- a/prolog/engine.py +++ b/prolog/engine.py @@ -13,19 +13,12 @@ import urllib def strip_html(text): return html.unescape(re.sub(r']*>', '', text)) -# Create a new pengine, initialize it with [code] and return Prolog's reply. -# The engine is destroyed after answering one query. If [query] is given, the -# first answer is returned and the engine destroyed. -def create(code='', query='', timeout=10): - opts = {'format': 'json-html', 'destroy': True, 'src_text': code} - if query: - opts['ask'] = query +# Create a new pengine and initialize it with [code]. Return engine ID and a +# list of messages from Prolog. +def create(code='', timeout=10): + opts = {'format': 'json-html', 'destroy': False, 'src_text': code} reply, output = request('POST', '/pengine/create', body=json.dumps(opts), timeout=timeout) - - # If query was given, the actual reply is nested in create/destroy objects. - if query: - reply = reply['answer']['data'] - return reply, output + return reply.get('id'), output def ask(engine, query, timeout=10): return send(engine, 'ask(({}),[])'.format(query), timeout=timeout) @@ -117,9 +110,10 @@ def pretty_vars(data): result += [strip_html(b) for b in data['residuals']] return ',\n'.join(result) if result else 'true' -# Get all solutions to [query] given background knowledge [code] that are found -# within [timeout] seconds. -def run(code, query, timeout): +# Run [query] in the pengine with id [engine] and return the list of answers +# found within [timeout] seconds. If a timeout occurs before the query is done, +# 'timed out' is appended as the last answer. +def ask_all(engine, query, timeout): # Returns a tuple ((bindings, constraints), error, more?) for one answer. def process_answer(reply): # When an engine is destroyed, a nested data object has the actual @@ -146,52 +140,34 @@ def run(code, query, timeout): return None, error, False start = time.monotonic() - result, messages = [], [] - engine = None + answers, messages = [], [] try: - # Create a new pengine. - reply, output = create(code=code, timeout=timeout) - messages += output - if reply.get('event') != 'create': - raise Exception('System error: creating pengine') - engine = reply['id'] - if 'error' in map(itemgetter(0), messages): - return None, messages - # Run the query. - real_timeout = timeout - (time.monotonic()-start) - if real_timeout <= 0: - raise socket.timeout() - reply, output = ask(engine, query, real_timeout) + reply, output = ask(engine, query, timeout) messages += output if 'error' in map(itemgetter(0), output): - return None, messages - - bindings, error, more = process_answer(reply) - if bindings: - result.append(bindings) + return answers, messages + answer, error, more = process_answer(reply) + if answer: + answers.append(answer) if error: messages.append(error) - # Continue while there are more potential answers. + # Continue while there are more potential answers and time remaining. while more: real_timeout = timeout - (time.monotonic()-start) if real_timeout <= 0: raise socket.timeout() reply, output = next(engine, timeout=real_timeout) messages += output - bindings, error, more = process_answer(reply) - if bindings: - result.append(bindings) + answer, error, more = process_answer(reply) + if answer: + answers.append(answer) if error: messages.append(error) except socket.timeout as ex: - result.append('timed out') - finally: - if engine: - destroy(engine) - - return result, messages + answers.append('timed out') + return answers, messages # Basic sanity check. diff --git a/server/prolog_session.py b/server/prolog_session.py index 768f820..ee8dba3 100644 --- a/server/prolog_session.py +++ b/server/prolog_session.py @@ -47,10 +47,10 @@ class PrologSession(object): if self._engine_id is not None: prolog.engine.stop(self._engine_id) self._engine_id = None - reply, output = prolog.engine.create(code=code) - if reply.get('event') != 'create': + engine_id, output = prolog.engine.create(code=code) + if not engine_id: raise Exception('System error: could not create a prolog engine') - self._engine_id = reply['id'] + self._engine_id = engine_id messages = [text for text in map(operator.itemgetter(1), output)] status = 'error' if 'error' in map(operator.itemgetter(0), output) else 'ok' return messages, status, False -- cgit v1.2.1