Register a plugin, or plugins to be managed and recognized by the plugin manager.
        Will take a plugin instance, file where a plugin / plugin(s) reside, parent directory
        that holds plugin(s), or sub-folders with plugin(s).

        Will optionally "activate" the plugins, and perform any operations defined in their "activate" method.

        :param plugin: Plugin Instance to register.
        :param plugin_file: str: File (full path) to scan for Plugins.
        :param directory: str: Directory to perform a recursive scan on for Plugins.
        :param skip_types: list: Types of plugins to skip when found, during a scan / search.
        :param override: bool: Whether or not to override registered plugin when it's being registered again.
        :param activate: bool: Whether or not to activate the plugins upon registration.
        :return: Does not Return.

def register(self, plugin=None, plugin_file=None, directory=None, skip_types=None, override=False, activate=True):
        """
        Register a plugin, or plugins to be managed and recognized by the plugin manager.
        Will take a plugin instance, file where a plugin / plugin(s) reside, parent directory
        that holds plugin(s), or sub-folders with plugin(s).

        Will optionally "activate" the plugins, and perform any operations defined in their "activate" method.

        :param plugin: Plugin Instance to register.
        :param plugin_file: str: File (full path) to scan for Plugins.
        :param directory: str: Directory to perform a recursive scan on for Plugins.
        :param skip_types: list: Types of plugins to skip when found, during a scan / search.
        :param override: bool: Whether or not to override registered plugin when it's being registered again.
        :param activate: bool: Whether or not to activate the plugins upon registration.
        :return: Does not Return.
        """
        # Double verify that there's types to skip. We don't want to register "Base" types (Plugin)

        if not isinstance(skip_types, list):
            skip_types = [skip_types]
            logger.debug("Skip Types must be a list. Created list with values passed.")

        if skip_types is None:
            skip_types = [Plugin]
        else:
            skip_types.append(Plugin)

        # Check if they've passed a method of registration!
        if plugin is None and plugin_file is None and directory is None:
            raise PluginException("Unable to perform registration without a plugin, module, or directory.")

        # First we'll check if they're registering via directory (Scanning)
        # as it might be best for bigger applications / apps with many plugins to register them via
        # a folder, where plugins are expected!
        if directory is not None:
            plugins_in_dir = PluginManager.scan_for_plugins(directory)
            # Loop through all the plugins in the directory, associated by file -> list[] (or none)
            for file, plugins in plugins_in_dir.items():
                # If there's no plugins in that file then just continue.
                if plugins is None:
                    continue

                for plugin in plugins:
                    # If there's a duplicate plugin and we're not overriding, then we'll skip it.
                    if plugin.name in self.plugins:
                        if not override:
                            logger.warn("Failed to register %s: Duplicate plugin found!" % plugin.name)
                            continue

                    # Now verify if we're supposed to skip the type of the plugin that's being attempted to register.
                    # Useful when plugins classes extend a base-class (Plugin, for example)
                    # but you don't want to register the base class.
                    if type(plugin) in skip_types:
                        logger.warn(
                            "Skipping registration of %s, as it's not to be registered." % plugin.__class__.__name__)
                        continue

                    # Assign the plugin (via name) to the dictionary of registered plugins
                    self.plugins[plugin.name] = plugin
                    # Give a little output of the plugin!
                    logger.debug("Registered plugin %s from %s in %s" % (plugin.name, file, directory))

                    # Then if we're going to activate the plugin, do so!
                    if activate:
                        self.plugins[plugin.name].activate()

        # Now we're going to check if they're registering the plugins
        # either by file, or module
        if plugin_file is not None:
            # If the plugin_file is not a module, then we're going to verify the file actually exists!
            if not inspect.ismodule(plugin_file):
                # Verify if there's a ~ (Home dir call) inside the path, and if so then expand it.
                plugin_file = os.path.expanduser(plugin_file)
                # Then verify if the path of the plugin exists, raising an exception if not!
                if not os.path.exists(plugin_file):
                    raise FileNotFoundError("Unable to locate file %s" % plugin_file)

            # Next after verifying, we get all the plugins inside the file or module.`
            plugins_in_file = PluginManager.get_plugins_in_module(plugin_file)
            # If there's no plugins inside, then we're going to throw an exception. There's nothing to register in here.
            if plugins_in_file is None or len(plugins_in_file) == 0:
                raise PluginException("Unable to locate plugins inside %s" % plugin_file)

            # Loop through every plugin inside the file/module and attempt to register it.
            for fplugin in plugins_in_file:
                # If there's a duplicate plugin and we're not overriding, then we'll skip it.
                if fplugin.name in self.plugins:
                    if not override:
                        logger.warn("Failed to register %s: Duplicate plugin found!" % fplugin.name)
                        continue

                # Now verify if we're supposed to skip the type of the plugin that's being attempted to register.
                # Useful when plugins classes extend a base-class (Plugin, for example)
                # but you don't want to register the base class.
                if type(fplugin) in skip_types:
                    logger.warn(
                        "Skipping registration of %s, as it's not to be registered." % fplugin.__class__.__name__)
                    continue

                # Assign the plugin (via name) to the dictionary of registered plugins
                self.plugins[fplugin.name] = fplugin
                # Give a little output of the plugin!
                logger.debug("Registered plugin %s from %s %s" % (
                    fplugin.name, "module" if inspect.ismodule(plugin_file) else "file",
                    get_filename(plugin_file) if not inspect.ismodule(plugin_file) else plugin_file.__name__)
                             )

                # Then if we're going to activate the plugin, do so!
                if activate:
                    self.plugins[fplugin.name].activate()

        # Now we're checking if they actually passed a plugin instance to register.
        if plugin is not None:
            # If it's already in the plugins and we're not overriding, then we'll skip it.
            if plugin.name in self.plugins:
                if override is False:
                    return

            # Otherwise register the plugin, and (potentially) activate it!
            self.plugins[plugin.name] = plugin
            logger.debug("Registered plugin %s" % plugin.name)
            if activate:
                self.plugins[plugin.name].activate()