def __loadPlugin(self, plugin, package_abspath, package_name=None):
        """Load plugin, plugin is a python package with `__import__`.

        :param plugin: Dynamically loaded plugin modules

        :param package_abspath: The package absolute directory

        :param package_name: Plugin package names (directories under plugins), such as PluginDemo
        """
        #: Detection plugin information
        if hasattr(plugin, "__plugin_name__") and \
                hasattr(plugin, "__version__") and \
                hasattr(plugin, "__description__") and \
                hasattr(plugin, "__author__") and \
                hasattr(plugin, "getPluginClass"):
            try:
                #: Get plugin information
                pluginInfo = self.__getPluginInfo(plugin, package_abspath, package_name)
                #: Get the plugin main class and instantiate it
                p = plugin.getPluginClass()
                i = p()
            except Exception as e:
                raise e
            #: Subsequent methods are not executed when not enabled
            if pluginInfo["plugin_state"] != "enabled":
                self.__plugins.append(pluginInfo)
                return
            #: Update plugin information
            pluginInfo.update(plugin_instance=i)
            #: Run the *run* method of the plugin main class
            if hasattr(i, "run"):
                #: Run once only when loading
                i.run()
            #: Register the template extension point
            if hasattr(i, "register_tep"):
                """ Template extension point requirements:
                format:
                    plugin_tep = {tep:dict(HTMLFile=str, HTMLString=str), tep...}

                returns:
                    return {tep_1: HTMLFile(str), tep_2: HTMLString(str)}

                explanation:
                    1. This must be dict, where key means that tep is the extension point identifier,
                        and each extension point can contain only one template type,
                        either HTML or string, which requires STR type, and other types trigger exceptions
                    2. HTML template type suffix for `html` or `htm` as template file (the other as pure HTML code),
                        to be real, will adopt a `render_template` way rendering,
                        using template type can be specified when rendering and introduced to additional data
                """
                tep = i.register_tep()
                if isinstance(tep, dict):
                    newTep = dict()
                    for event, tpl in tep.items():
                        if isinstance(tpl, string_types):
                            if os.path.splitext(tpl)[-1] in (".html", ".htm"):
                                if os.path.isfile(os.path.join(pluginInfo["plugin_tpl_path"], tpl.split("@")[-1] if "@" in tpl and self.stpl is True else tpl)):
                                    newTep[event] = dict(HTMLFile=tpl)
                                else:
                                    raise jinja2.TemplateNotFound("TEP Template File Not Found: %s" % tpl)
                            else:
                                newTep[event] = dict(HTMLString=jinja2.Markup(tpl))
                        else:
                            raise PluginError("Invalid TEP Format")
                    pluginInfo.update(plugin_tep=newTep)
                    self.logger.info("Register TEP Success")
                else:
                    raise PluginError("Register TEP Failed, not a dict")
            #: Register context extension points
            if hasattr(i, "register_hep"):
                cep = i.register_hep()
                if isinstance(cep, dict):
                    pluginInfo.update(plugin_hep=cep)
                    self.logger.info("Register HEP Success")
                else:
                    raise PluginError("Register HEP Failed, not a dict")
            #: Register the blueprint extension point
            if hasattr(i, "register_bep"):
                bep = i.register_bep()
                if isinstance(bep, dict):
                    pluginInfo.update(plugin_bep=bep)
                    self.logger.info("Register BEP Success")
                else:
                    raise PluginError("Register BEP Failed, not a dict")
            #: Register the css extension point
            if hasattr(i, "register_yep"):
                """Register the plugin's cascading style sheet (CSS) file, requirements:
                format:
                    plugin_yep = {yep: css, yep: [css, ...]}

                returns:
                    return {yep: [css, ...], yep: [css, ...], ...}

                explanation:
                    1. This must be dict, and a key or an extension is the name of the page that CSS suggests to be introduced,
                        and each extension can be a single CSS or a set of CSS
                    2. CSS suffix must be `.css`, and real
                """
                yep = i.register_yep()
                if isinstance(yep, dict):
                    newYep = dict()
                    for event, css in yep.items():
                        if isinstance(css, string_types):
                            if os.path.isfile(os.path.join(pluginInfo["plugin_ats_path"], css)) and css.endswith(".css"):
                                newYep[event] = [self.static_url_path + "/" + css]
                            else:
                                raise CSSLoadError("YEP CSS File Is Invalid: %s" % css)
                        elif isinstance(css, (list, tuple)):
                            newCss = []
                            for ac in css:
                                if isinstance(ac, string_types) and os.path.isfile(os.path.join(pluginInfo["plugin_ats_path"], ac)) and ac.endswith(".css"):
                                    newCss.append(self.static_url_path + "/" + ac)
                                else:
                                    raise CSSLoadError("YEP CSS File Is Invalid: %s" % ac)
                            newYep[event] = newCss
                        else:
                            raise PluginError("Invalid YEP Format")
                    pluginInfo.update(plugin_yep=newYep)
                    self.logger.info("Register YEP Success")
                else:
                    raise PluginError("Register YEP Failed, not a dict")
            #: Register the dfp with a func
            if hasattr(i, "register_dfp"):
                dfp = i.register_dfp()
                if isinstance(dfp, dict):
                    for cuin,func in dfp.items():
                        self.push_func(cuin,func)
                else:
                    raise PluginError("Register DFP Failed, not a dict")
            #: TODO: Register signal extension points `sep`
            #: Add to the global plugin
            if hasattr(i, "run") or hasattr(i, "register_tep") or hasattr(i, "register_hep") or hasattr(i, "register_bep") or hasattr(i, "register_yep") or hasattr(i, "register_dfp"):
                self.__plugins.append(pluginInfo)
            else:
                self.logger.error("The current package does not have the `run` or `register_tep` or `register_hep` or `register_bep` or `register_yep` method")
Load plugin, plugin is a python package with `__import__`.

        :param plugin: Dynamically loaded plugin modules

        :param package_abspath: The package absolute directory

        :param package_name: Plugin package names (directories under plugins), such as PluginDemo