Пример #1
0
    def _register_helper(plugin,
                         context,
                         *args,
                         _spf=None,
                         _plugin_name=None,
                         _url_prefix=None,
                         **kwargs):
        error_str = "Plugin must be initialised using the " \
                    "Sanic Plugins Framework"
        assert _spf is not None, error_str
        assert _plugin_name is not None, error_str
        _app = _spf._app
        assert _app is not None, error_str

        reg = PluginRegistration(spf=_spf,
                                 plugin_name=_plugin_name,
                                 url_prefix=_url_prefix)
        context['log'] = partial(_spf.log, reg=reg)
        context['url_for'] = partial(_spf.url_for, reg=reg)
        continue_flag = plugin.on_before_registered(context, *args, **kwargs)
        if continue_flag is False:
            return plugin

        # Routes
        for r in plugin._routes:
            # attach the plugin name to the handler so that it can be
            # prefixed properly in the router
            if isinstance(_app, Blueprint):
                # blueprint always handles adding __blueprintname__
                # So we identify ourselves here a different way.
                handler_name = r.handler.__name__
                r.handler.__name__ = "{}.{}".format(_plugin_name, handler_name)
            else:
                r.handler.__blueprintname__ = _plugin_name
            # Prepend the plugin URI prefix if available
            uri = _url_prefix + r.uri if _url_prefix else r.uri
            _spf._plugin_register_route(
                r.handler, plugin, context,
                uri[1:] if uri.startswith('//') else uri, *r.args, **r.kwargs)

        # Middleware
        for m in plugin._middlewares:
            _spf._plugin_register_middleware(m.middleware, plugin, context,
                                             *m.args, **m.kwargs)

        # Exceptions
        for e in plugin._exceptions:
            _spf._plugin_register_exception(e.handler, plugin, context,
                                            *e.exceptions, **e.kwargs)

        # Listeners
        for event, listeners in plugin._listeners.items():
            for listener in listeners:
                _spf._plugin_register_listener(event, listener, plugin)

        # # this should only ever run once!
        plugin.registrations.add(reg)
        plugin.on_registered(context, reg, *args, **kwargs)

        return reg
    def _register_helper(plugin, context, *args, _spf=None, _plugin_name=None,
                         _url_prefix=None, **kwargs):
        error_str = "Plugin must be initialised using the " \
                    "Sanic Plugins Framework."
        assert _spf is not None, error_str
        assert _plugin_name is not None, error_str
        _app = _spf._app
        assert _app is not None, error_str

        reg = PluginRegistration(spf=_spf, plugin_name=_plugin_name,
                                 url_prefix=_url_prefix)
        context['log'] = partial(_spf.log, reg=reg)
        context['url_for'] = partial(_spf.url_for, reg=reg)
        continue_flag = plugin.on_before_registered(context, *args, **kwargs)
        if continue_flag is False:
            return plugin

        # Routes
        [_spf._register_route_helper(r, _spf, plugin, context, _plugin_name,
                                     _url_prefix)
         for r in plugin._routes]

        # Websocket routes
        [_spf._register_websocket_route_helper(w, _spf, plugin, context,
                                               _plugin_name, _url_prefix)
         for w in plugin._ws]

        # Static routes
        [_spf._register_static_helper(s, _spf, plugin, context, _plugin_name,
                                      _url_prefix)
         for s in plugin._static]

        # Middleware
        [_spf._register_middleware_helper(m, _spf, plugin, context)
         for m in plugin._middlewares]

        # Exceptions
        for e in plugin._exceptions:
            _spf._plugin_register_exception(
                e.handler, plugin, context, *e.exceptions, **e.kwargs)

        # Listeners
        for event, listeners in plugin._listeners.items():
            for listener in listeners:
                if isinstance(listener, tuple):
                    listener, kwargs = listener
                _spf._plugin_register_listener(
                    event, listener, plugin, context, **kwargs)

        # # this should only ever run once!
        plugin.registrations.add(reg)
        plugin.on_registered(context, reg, *args, **kwargs)

        return reg
    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 = getattr(mod, 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):
                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, maybe under a different name?")
        self._plugin_names.add(name)
        shared_context = self.shared_context
        self._contexts[name] = context = SanicContext(
            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)