|
@@ -54,7 +54,7 @@ class RequestHandler(object):
|
|
|
|
|
|
def handle_request(self, reply):
|
|
def handle_request(self, reply):
|
|
"""Replies to a request from the top-of-stack generator, and returns a new request."""
|
|
"""Replies to a request from the top-of-stack generator, and returns a new request."""
|
|
- if not self.is_active():
|
|
|
|
|
|
+ if not self.generator_stack:
|
|
raise ValueError('handle_request cannot be called with an empty generator stack.')
|
|
raise ValueError('handle_request cannot be called with an empty generator stack.')
|
|
|
|
|
|
# Append the server's replies to the list of replies.
|
|
# Append the server's replies to the list of replies.
|
|
@@ -68,20 +68,19 @@ class RequestHandler(object):
|
|
# Silence pylint's warning about catching Exception.
|
|
# Silence pylint's warning about catching Exception.
|
|
# pylint: disable=I0011,W0703
|
|
# pylint: disable=I0011,W0703
|
|
try:
|
|
try:
|
|
- while self.generator_stack[-1]["finished_requests"]:
|
|
|
|
|
|
+ if self.generator_stack[-1]["finished_requests"]:
|
|
gen = self.generator_stack[-1]
|
|
gen = self.generator_stack[-1]
|
|
gen["pending_requests"] = gen["generator"].send(gen["replies"])
|
|
gen["pending_requests"] = gen["generator"].send(gen["replies"])
|
|
gen["finished_requests"] = False
|
|
gen["finished_requests"] = False
|
|
gen["replies"] = None
|
|
gen["replies"] = None
|
|
- else:
|
|
|
|
- return self.pop_requests()
|
|
|
|
|
|
+ return self.pop_requests()
|
|
|
|
|
|
except KnownRequestHandled:
|
|
except KnownRequestHandled:
|
|
pass
|
|
pass
|
|
except StopIteration:
|
|
except StopIteration:
|
|
# Done, so remove the generator
|
|
# Done, so remove the generator
|
|
self.pop_generator()
|
|
self.pop_generator()
|
|
- if self.is_active():
|
|
|
|
|
|
+ if self.generator_stack:
|
|
# This generator was called from another generator.
|
|
# This generator was called from another generator.
|
|
# Append 'None' to the caller's list of replies.
|
|
# Append 'None' to the caller's list of replies.
|
|
self.append_reply(None)
|
|
self.append_reply(None)
|
|
@@ -91,7 +90,7 @@ class RequestHandler(object):
|
|
except primitive_functions.PrimitiveFinished as ex:
|
|
except primitive_functions.PrimitiveFinished as ex:
|
|
# Done, so remove the generator
|
|
# Done, so remove the generator
|
|
self.pop_generator()
|
|
self.pop_generator()
|
|
- if self.is_active():
|
|
|
|
|
|
+ if self.generator_stack:
|
|
# This generator was called from another generator.
|
|
# This generator was called from another generator.
|
|
# Append the callee's result to the caller's list of replies.
|
|
# Append the callee's result to the caller's list of replies.
|
|
self.append_reply(ex.result)
|
|
self.append_reply(ex.result)
|
|
@@ -111,10 +110,6 @@ class RequestHandler(object):
|
|
"""Sets the finished_requests flag in the top-of-stack tuple."""
|
|
"""Sets the finished_requests flag in the top-of-stack tuple."""
|
|
self.generator_stack[-1]["finished_requests"] = True
|
|
self.generator_stack[-1]["finished_requests"] = True
|
|
|
|
|
|
- def has_pending_requests(self):
|
|
|
|
- """Tests if the top-of-stack generator has pending requests."""
|
|
|
|
- return not self.generator_stack[-1]["finished_requests"]
|
|
|
|
-
|
|
|
|
def push_generator(self, gen):
|
|
def push_generator(self, gen):
|
|
"""Pushes a new generator onto the stack."""
|
|
"""Pushes a new generator onto the stack."""
|
|
dd = defaultdict(lambda : None)
|
|
dd = defaultdict(lambda : None)
|
|
@@ -130,9 +125,8 @@ class RequestHandler(object):
|
|
# print('Popped generator %s. Generator count: %d' % (gen, len(self.generator_stack)))
|
|
# print('Popped generator %s. Generator count: %d' % (gen, len(self.generator_stack)))
|
|
# Pop any exception handlers defined by the generator.
|
|
# Pop any exception handlers defined by the generator.
|
|
top_of_stack_index = len(self.generator_stack)
|
|
top_of_stack_index = len(self.generator_stack)
|
|
- while len(self.exception_handlers) > 0:
|
|
|
|
- stack_index, _ = self.exception_handlers[-1]
|
|
|
|
- if stack_index == top_of_stack_index:
|
|
|
|
|
|
+ while self.exception_handlers:
|
|
|
|
+ if self.exception_handlers[-1][0] == top_of_stack_index:
|
|
# Pop exception handlers until exception_handlers is empty or until
|
|
# Pop exception handlers until exception_handlers is empty or until
|
|
# we find an exception handler that is not associated with the popped
|
|
# we find an exception handler that is not associated with the popped
|
|
# generator.
|
|
# generator.
|
|
@@ -152,7 +146,7 @@ class RequestHandler(object):
|
|
"""Handles the given exception. A Boolean is returned that tells if
|
|
"""Handles the given exception. A Boolean is returned that tells if
|
|
the exception was handled."""
|
|
the exception was handled."""
|
|
# print('Exception thrown from %s: %s' % (str(self.generator_stack[-1]), str(exception)))
|
|
# print('Exception thrown from %s: %s' % (str(self.generator_stack[-1]), str(exception)))
|
|
- while len(self.exception_handlers) > 0:
|
|
|
|
|
|
+ while self.exception_handlers:
|
|
# Pop the top-of-stack exception handler.
|
|
# Pop the top-of-stack exception handler.
|
|
stack_index, handlers = self.exception_handlers.pop()
|
|
stack_index, handlers = self.exception_handlers.pop()
|
|
|
|
|
|
@@ -193,7 +187,7 @@ class RequestHandler(object):
|
|
|
|
|
|
# Then pop every generator from the stack and make it crash.
|
|
# Then pop every generator from the stack and make it crash.
|
|
stack_trace = []
|
|
stack_trace = []
|
|
- while len(self.generator_stack) > 0:
|
|
|
|
|
|
+ while self.generator_stack:
|
|
top_entry = self.generator_stack.pop()
|
|
top_entry = self.generator_stack.pop()
|
|
if top_entry["function_origin"] is None:
|
|
if top_entry["function_origin"] is None:
|
|
# Skip this function.
|
|
# Skip this function.
|
|
@@ -224,32 +218,26 @@ class RequestHandler(object):
|
|
A list of requests and a Boolean are returned. The latter is True
|
|
A list of requests and a Boolean are returned. The latter is True
|
|
if there are no more requests to process, and false otherwise."""
|
|
if there are no more requests to process, and false otherwise."""
|
|
requests = self.generator_stack[-1]["pending_requests"]
|
|
requests = self.generator_stack[-1]["pending_requests"]
|
|
- if requests is None or len(requests) == 0:
|
|
|
|
- # Couldn't find a request for the state to handle.
|
|
|
|
- self.set_finished_requests_flag()
|
|
|
|
- return requests
|
|
|
|
-
|
|
|
|
- for i, elem in enumerate(requests):
|
|
|
|
- if elem[0] in self.handlers:
|
|
|
|
- # The kernel should handle known requests.
|
|
|
|
- if i > 0:
|
|
|
|
- # Handle any requests that precede the known request first.
|
|
|
|
- pre_requests = requests[:i]
|
|
|
|
- del requests[:i]
|
|
|
|
- return pre_requests
|
|
|
|
-
|
|
|
|
- # The known request must be the first element in the list. Pop it.
|
|
|
|
- requests.pop(0)
|
|
|
|
|
|
+ if requests:
|
|
|
|
+ if requests[0][0] in self.handlers:
|
|
|
|
+ # First element is a known request
|
|
|
|
+ elem = requests.pop(0)
|
|
|
|
|
|
# The list of requests might be empty now. If so, then flag this
|
|
# The list of requests might be empty now. If so, then flag this
|
|
# batch of requests as finished.
|
|
# batch of requests as finished.
|
|
- if len(requests) == 0:
|
|
|
|
|
|
+ if not requests:
|
|
self.set_finished_requests_flag()
|
|
self.set_finished_requests_flag()
|
|
|
|
|
|
# Handle the request.
|
|
# Handle the request.
|
|
- _, request_args = elem
|
|
|
|
- self.handlers[elem[0]](request_args)
|
|
|
|
|
|
+ self.handlers[elem[0]](elem[1])
|
|
raise KnownRequestHandled()
|
|
raise KnownRequestHandled()
|
|
|
|
+ else:
|
|
|
|
+ for i, elem in enumerate(requests):
|
|
|
|
+ if elem[0] in self.handlers:
|
|
|
|
+ # Handle any requests that precede the known request first.
|
|
|
|
+ pre_requests = requests[:i]
|
|
|
|
+ del requests[:i]
|
|
|
|
+ return pre_requests
|
|
|
|
|
|
# We couldn't find a known request in the batch of requests, so we might as well
|
|
# We couldn't find a known request in the batch of requests, so we might as well
|
|
# handle them all at once then.
|
|
# handle them all at once then.
|