Skip to content

Plugin info update #176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jan 12, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fixed not being able to get the PluginInfo instance during load on mo…
…dule level or in load
  • Loading branch information
Ayuto committed Jan 2, 2017
commit 9582497032f7ccb474932a9a81210d1b153cc186
24 changes: 17 additions & 7 deletions addons/source-python/packages/source-python/plugins/instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ def __init__(self, plugin_name, manager):
self.plugin_name = plugin_name
self.directory = self.manager.get_plugin_directory(plugin_name)
self.file_path = self.directory / plugin_name + '.py'
self.info = self.manager._create_plugin_info(self.plugin_name)
self.info._create_public_convar()
self._plugin = None

# Fall back to the default logger if none was set
if self.logger is None:
Expand Down Expand Up @@ -86,16 +89,23 @@ def __init__(self, plugin_name, manager):
raise PluginFileNotFoundError

# Get the import name
self.import_name = (self.manager.base_import + plugin_name +
self.import_name = (self.manager.base_import + plugin_name +
'.' + plugin_name)

# Import the plugin
def _load(self):
"""Actually load the plugin."""
self._plugin = import_module(self.import_name)

# Set the globals value
self.globals = {
x: getattr(self._plugin, x) for x in dir(self._plugin)}

# Add this instance to the plugin info for easier access
self.info = self.manager._create_plugin_info(self.plugin_name)
self.info._create_public_convar()
if 'load' in self.globals:
self.globals['load']()

def _unload(self):
"""Actually unload the plugin."""
if 'unload' in self.globals:
# Use a try/except here to still allow the plugin to be unloaded
try:
self.globals['unload']()
except:
except_hooks.print_exception()
53 changes: 25 additions & 28 deletions addons/source-python/packages/source-python/plugins/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ class PluginManager(OrderedDict):

instance = None
prefix = None
logger = None
translations = None

def __init__(self, base_import=''):
"""Called when the class instance is initialized."""
# Re-call OrderedDict's __init__ to properly setup the object
super().__init__()
self.logger = None
self.translations = None
self._base_import = base_import

# Does the object have a logger set?
Expand All @@ -71,19 +71,30 @@ def __init__(self, base_import=''):
if self.translations is None:
self.translations = _plugin_strings

def _create_plugin_instance(self, plugin_name):
"""Create a new plugin instance.

:rtype: LoadedPlugin
"""
# TODO:
# Rename "instance" to a better name? Perphaps completely remove it?
# Subclasses should implement this method instead.
return self.instance(plugin_name, self)

def __missing__(self, plugin_name):
"""Try to load a plugin that is not loaded."""
# Try to get the plugin's instance
try:
instance = self._create_plugin_instance(plugin_name)

# Get the plugin's instance
instance = self.instance(plugin_name, self)
# Add the instance here, so we can use get_plugin_instance() etc.
# within the plugin itself before the plugin has been fully
# loaded. This is also required e.g. for retrieving the PluginInfo
# instance.
self[plugin_name] = instance

# Does the plugin have a load function?
if 'load' in instance.globals:

# Call the plugin's load function
instance.globals['load']()
# Actually load the plugin
instance._load()

# Was the file not found?
# We use this check because we already printed the error to console
Expand All @@ -94,6 +105,10 @@ def __missing__(self, plugin_name):

# Was a different error encountered?
except:
try:
super().__delitem__(plugin_name)
except KeyError:
pass

# Get the error
error = sys.exc_info()
Expand All @@ -120,38 +135,20 @@ def __missing__(self, plugin_name):
# Return None as the value to show the addon was not loaded
return None

# Add the plugin to the dictionary with its instance
self[plugin_name] = instance
on_plugin_loaded_manager.notify(plugin_name)
return instance

def __delitem__(self, plugin_name):
"""Remove a plugin from the manager."""
# Is the plugin in the dictionary?
if plugin_name not in self:

# Do nothing
return

# Print a message about the plugin being unloaded
self.logger.log_message(self.prefix + self.translations[
'Unloading'].get_string(plugin=plugin_name))

# Does the plugin have an unload function?
if 'unload' in self[plugin_name].globals:

# Use a try/except here to still allow the plugin to be unloaded
try:

# Call the plugin's unload function
self[plugin_name].globals['unload']()

# Was an exception raised?
except:

# Print the error to console, but
# allow the plugin to still be unloaded
except_hooks.print_exception()
self[plugin_name]._unload()

# Remove all modules from sys.modules
self._remove_modules(plugin_name)
Expand Down