def create_temporary_request_context(self, request): request_hash = id(request) new_ctx = ContextDict(self, None, {'id': 'shared request contexts'}) shared_context = self.shared_context shared_request = shared_context.get('request', False) if not shared_request: shared_context['request'] = shared_request = new_ctx shared_request[request_hash] =\ ContextDict(self, None, {'request': request, 'id': "shared request context for request {}" .format(id(request))}) for name, _p in self._plugins_context.items(): if not (isinstance(_p, ContextDict) and 'instance' in _p and isinstance(_p['instance'], SanicPlugin)): continue if not ('context' in _p and isinstance(_p['context'], ContextDict)): continue _p_context = _p['context'] if 'request' not in _p_context: _p_context['request'] = p_request = ContextDict( self, None, {'id': 'private request contexts'}) else: p_request = _p_context.request p_request[request_hash] =\ ContextDict(self, None, {'request': request, 'id': "private request context for {} on request {}" .format(name, id(request))})
def test_context_get_private_from_slots(spf): context = ContextDict(spf, None) context.set("t1", "hello world") d = context.__getattr__('_dict') d2 = getattr(context, '_dict') assert isinstance(d, dict) assert "t1" in d assert d == d2
def test_context_update(spf): context = ContextDict(spf, None) child_context = context.create_child_context() context['t1'] = "hello world" child_context['t2'] = "hello2" assert child_context['t1'] == "hello world" child_context.update({'t1': "test1", 't2': "test2"}) assert context['t1'] == "test1" assert child_context['t2'] == "test2"
def test_context_replace(spf): context = ContextDict(spf, None) child_context = context.create_child_context() context['t1'] = "hello world" assert child_context['t1'] == "hello world" child_context['t1'] = "goodbye world" assert context['t1'] != "goodbye world" del(child_context['t1']) child_context.replace('t1', 'goodbye world') assert context['t1'] == "goodbye world"
def test_context_pickle(spf): context = ContextDict(spf, None) child_context = context.create_child_context() child_context['t1'] = "hello world" p_bytes = pickle.dumps(child_context) un_p = pickle.loads(p_bytes) # the spf and the parent context are not the same as before, because # their state got pickled and unpicked too assert un_p._spf != spf assert un_p._parent_context != context assert un_p['t1'] == "hello world"
def test_context_items_keys_values(spf): context = ContextDict(spf, None) context["t1"] = "hello world" context["t2"] = "hello 2" items = context.items() assert len(items) == 2 keys = context.keys() assert len(keys) == 2 assert "t1" in list(keys) vals = context.values() assert len(vals) == 2 assert "hello world" in list(vals)
def _recreate(cls, app): self = super(SanicPluginsFramework, cls).__new__(cls) self._running = False self._app = app self._loop = None self._plugin_names = set() # these deques get replaced with frozen tuples at runtime self._pre_request_middleware = deque() self._post_request_middleware = deque() self._pre_response_middleware = deque() self._post_response_middleware = deque() self._contexts = ContextDict(self, None) self._contexts['shared'] = ContextDict(self, None, {'app': app}) self._contexts['_plugins'] = ContextDict(self, None, {'spf': self}) return self
def test_recursive_dict(spf): context = ContextDict(spf, None) context['t1'] = "hello world" c2 = context.create_child_context() c2['t2'] = "hello 2" c3 = c2.create_child_context() c3['t3'] = "hello 3" context._parent_context = c3 # This is dodgy, why would anyone do this? exceptions = [] try: _ = c2['t4'] except RuntimeError as e: assert len(e.args) > 0 assert "recursive" in str(e.args[0]).lower() exceptions.append(e) finally: assert len(exceptions) == 1
def __new__(cls, app, *args, **kwargs): assert app, "SPF must be given a valid Sanic App to work with." assert isinstance(app, Sanic) or isinstance(app, Blueprint),\ "SPF only works with Sanic Apps or Blueprints. " \ "Please pass in an app instance to the SPF constructor." # An app _must_ only have one spf instance associated with it. # If there is already one registered on the app, return that one. try: instance = app.config[APP_CONFIG_KEY] assert isinstance(instance, cls),\ "This app is already registered to a different type of " \ "Sanic Plugins Framework!" return instance except AttributeError: # app must then be a blueprint try: instance = getattr(app, APP_CONFIG_KEY) assert isinstance(instance, cls),\ "This Blueprint is already registered to a different " \ "type of Sanic Plugins Framework!" return instance except AttributeError: pass except KeyError: pass self = super(SanicPluginsFramework, cls).__new__(cls) self._running = False self._app = app self._logger = logging.getLogger(__name__) self._plugin_names = set() # these PQs get replaced with frozen tuples at runtime self._pre_request_middleware = PriorityQueue() self._post_request_middleware = PriorityQueue() self._pre_response_middleware = PriorityQueue() self._post_response_middleware = PriorityQueue() self._contexts = ContextDict(self, None) self._contexts['shared'] = ContextDict(self, None, {'app': app}) self._contexts['_plugins'] = ContextDict(self, None, {'spf': self}) if isinstance(app, Blueprint): self._patch_blueprint(app) else: self._patch_app(app) return self
def create_temporary_request_context(self, request): request_hash = id(request) new_ctx = ContextDict(self, None, {}) shared_context = self.shared_context shared_request = shared_context.get('request', False) if not shared_request: shared_context['request'] = shared_request = new_ctx shared_request[request_hash] =\ ContextDict(self, None, {'request': request}) for name, _p in self._plugins_context.items(): if isinstance(_p, ContextDict) and 'instance' in _p \ and isinstance(_p['instance'], SanicPlugin): if 'context' in _p and isinstance(_p['context'], ContextDict): _p_context = _p['context'] p_request = _p_context.get('request', False) if not p_request: _p_context['request'] = p_request = ContextDict( self, None, {}) p_request[request_hash] =\ ContextDict(self, None, {'request': request})
def test_context_set_contains_get(spf): context = ContextDict(spf, None) context.set("t1", "hello world") assert "t1" in context assert context.get("t1") == "hello world" exceptions = [] try: context.set("__weakref__", set()) except ValueError as e: exceptions.append(e) finally: assert len(exceptions) > 0
def test_context_del(spf): context = ContextDict(spf, None) context.set(1, "1") context.set(2, "2") context.set(3, "3") context.set(4, "4") del context[1] one = context.get(1, None) assert one is None exceptions = [] try: #TODO: How do you even delete a slice? del context[2:4] except Exception as e: exceptions.append(e) finally: assert len(exceptions) > 0
def test_context_repr(spf): context = ContextDict(spf, None) context['t1'] = "hello world" s1 = repr(context) assert s1 == "ContextDict({'t1': 'hello world'})"
def register_plugin(self, plugin, *args, name=None, skip_reg=False, **kwargs): assert not self._running, "Cannot add, remove, or change plugins " \ "after the App has started serving." assert plugin, "Plugin must be a valid type! Do not pass in `None` " \ "or `False`" if isinstance(plugin, type): # We got passed in a Class. That's ok, we can handle this! module_name = getattr(plugin, '__module__') class_name = getattr(plugin, '__name__') lower_class = to_snake_case(class_name) try: mod = importlib.import_module(module_name) try: plugin = mod.getattr(lower_class) except AttributeError: plugin = mod # try the module-based resolution next except ImportError: raise if ismodule(plugin): # We got passed in a module. That's ok, we can handle this! try: # look for '.instance' on the module plugin = getattr(plugin, 'instance') assert plugin is not None except (AttributeError, AssertionError): # now look for the same name, # like my_module.my_module on the module. try: plugin_module_name = getattr(plugin, '__name__') assert plugin_module_name and len(plugin_module_name) > 0 plugin_module_name = plugin_module_name.split('.')[-1] plugin = getattr(plugin, plugin_module_name) assert plugin is not None except (AttributeError, AssertionError): raise RuntimeError( "Cannot import this module as a Sanic Plugin.") assert isinstance(plugin, SanicPlugin),\ "Plugin must be derived from SanicPlugin" if name is None: try: name = str(plugin.__class__.__name__) assert name is not None except (AttributeError, AssertionError, ValueError, KeyError): self._logger.warning( "Cannot determine a name for {}, using UUID.".format( repr(plugin))) name = str(uuid1(None, None)) assert isinstance(name, str), \ "Plugin name must be a python unicode string!" associated_tuple = plugin.AssociatedTuple if name in self._plugin_names: # we're already registered on this SPF reg = plugin.find_plugin_registration(self) assoc = associated_tuple(plugin, reg) raise ValueError("Plugin {:s} is already registered!".format(name), assoc) if plugin.is_registered_on_framework(self): raise RuntimeError("Plugin already shows it is registered to this " "spf.") self._plugin_names.add(name) shared_context = self.shared_context self._contexts[name] = context = ContextDict( self, shared_context, {'shared': shared_context}) _p_context = self._plugins_context _plugin_reg = _p_context.get(name, None) if _plugin_reg is None: _p_context[name] = _plugin_reg = _p_context.create_child_context() _plugin_reg['name'] = name _plugin_reg['context'] = context if skip_reg: dummy_reg = PluginRegistration(spf=self, plugin_name=name, url_prefix=None) context['log'] = partial(self.log, reg=dummy_reg) context['url_for'] = partial(self.url_for, reg=dummy_reg) plugin.registrations.add(dummy_reg) # This indicates the plugin is not registered on the app _plugin_reg['instance'] = None _plugin_reg['reg'] = None return associated_tuple(plugin, dummy_reg) if _plugin_reg.get('instance', False): raise RuntimeError("The plugin we are trying to register already " "has a known instance!") reg = self._register_helper(plugin, context, *args, _spf=self, _plugin_name=name, **kwargs) _plugin_reg['instance'] = plugin _plugin_reg['reg'] = reg return associated_tuple(plugin, reg)