From 4025ab928d8c3e5e0647c659413989e6d73975a5 Mon Sep 17 00:00:00 2001 From: pjenvey Date: Fri, 1 Dec 2006 23:54:25 +0000 Subject: StackedObjectRestorer tests. fixed a couple edge cases: o get_saved_proxied_obj needed to delve down to allow access to older (overlaid) RegistryManagers' objects (test_restorer_nested_middleman) o save_registry_state needed to save all state, so restoration can get to every overlaid RegistryManagers' objects (test_restorer_middlemen_nested_evalexception). cleaned it up to do all the saving at once, instead of piecemeal --- paste/registry.py | 50 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 20 deletions(-) (limited to 'paste/registry.py') diff --git a/paste/registry.py b/paste/registry.py index ffc853f..57bd0c4 100644 --- a/paste/registry.py +++ b/paste/registry.py @@ -374,42 +374,52 @@ class StackedObjectRestorer(object): self.evalcontext_id = threadinglocal.local() def save_registry_state(self, environ): - """Save the current state (top of the stack) of the registry to the - saved_registry_states dict, keyed by the request's unique identifier""" + """Save the state of this request's registry (if it hasn't already been + saved) to the saved_registry_states dict, keyed by the request's unique + identifier""" registry = environ.get('paste.registry') - if not registry: - return - if not len(registry.reglist): - # No state to save + if not registry or not len(registry.reglist) or \ + get_request_id(environ) in self.saved_registry_states: + # No Registry, no state to save, or this request's state has + # already been saved return - # The current level of the stack to be saved - saved_reglist = registry.reglist[-1] - for stacked, obj in saved_reglist.itervalues(): - # Tweak the StackedObjectProxies we want to save state for -- - # change the _current_obj stategy to search for the original - # proxied object when ran from EvalException - if '_current_obj' not in stacked.__dict__: - self.enable_restoration(stacked) + self.saved_registry_states[get_request_id(environ)] = \ + registry.reglist[:] - # prepend instead of append: we're gathering the Registry stack in the - # opposite direction - self.saved_registry_states.setdefault(get_request_id(environ), - []).insert(0, saved_reglist) + # Tweak the StackedObjectProxies we want to save state for -- change + # the _current_obj stategy to search for the original proxied object + # when ran from EvalException + for reglist in registry.reglist: + for stacked, obj in reglist.itervalues(): + self.enable_restoration(stacked) def get_saved_proxied_obj(self, stacked, request_id): """Retrieve the saved object proxied by the specified StackedObjectProxy for the request identified by request_id""" # All state for the request identifed by request_id reglists = self.saved_registry_states[request_id] + # The top of the stack was current when the exception occurred - top_reglist = reglists[-1] - return top_reglist[id(stacked)][1] + stack_level = -1 + reglist = reglists[stack_level] + stacked_id = id(stacked) + # The StackedObjectProxy may not have been registered by the + # RegistryManager that was active when the exception was raised. If it + # wasn't, continue searching down the stack until it's found + while stacked_id not in reglist and -stack_level <= len(reglists): + stack_level -= 1 + reglist = reglists[stack_level] + return reglist[id(stacked)][1] def enable_restoration(self, stacked): """Replace the specified StackedObjectProxy's _current_obj method with _current_obj_evalexception: forces recovery of the saved proxied object during EvalException's EvalContext call""" + if '_current_obj' in stacked.__dict__: + # Restoration already enabled + return + orig_current_obj = stacked._current_obj def _current_obj_evalexception(self): request_id = restorer.in_evalcontext() -- cgit v1.2.1