Skip to content

Commit

Permalink
[commands] Add basic support for extensions.
Browse files Browse the repository at this point in the history
  • Loading branch information
Rapptz committed Jan 9, 2016
1 parent 0a07fc0 commit b87d5e5
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 1 deletion.
53 changes: 52 additions & 1 deletion discord/ext/commands/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import asyncio
import discord
import inspect
import importlib
import sys

from .core import GroupMixin, Command
from .view import StringView
Expand Down Expand Up @@ -78,6 +80,7 @@ def __init__(self, command_prefix, **options):
self.command_prefix = command_prefix
self.extra_events = {}
self.cogs = {}
self.extensions = {}

# internal helpers

Expand Down Expand Up @@ -262,7 +265,6 @@ def remove_listener(self, func, name=None):
except ValueError:
pass


def listen(self, name=None):
"""A decorator that registers another function as an external
event listener. Basically this allows you to listen to multiple
Expand Down Expand Up @@ -375,6 +377,55 @@ def remove_cog(self, name):
if name.startswith('on_'):
self.remove_listener(member)

# extensions

def load_extension(self, name):
if name in self.extensions:
return

lib = importlib.import_module(name)
try:
lib.setup(self)
except AttributeError:
raise discord.ClientException('extension does not have a setup function')

self.extensions[name] = lib

def unload_extension(self, name):
lib = self.extensions.get(name)
if lib is None:
return

# find all references to the module

# remove the cogs registered from the module
for cogname, cog in self.cogs.copy().items():
if cog.__module__ is lib:
self.remove_cog(cogname)

# first remove all the commands from the module
for command in self.commands.copy().values():
if command.module is lib:
command.module = None
if isinstance(command, GroupMixin):
command.recursively_remove_all_commands()
self.remove_command(command.name)

# then remove all the listeners from the module
for event_list in self.extra_events.copy().values():
remove = []
for index, event in enumerate(event_list):
if inspect.getmodule(event) is lib:
remove.append(index)

for index in reversed(remove):
del event_list[index]

# finally remove the import..
del lib
del self.extensions[name]
del sys.modules[name]

# command processing

@asyncio.coroutine
Expand Down
6 changes: 6 additions & 0 deletions discord/ext/commands/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,12 @@ def __init__(self, **kwargs):
self.commands = {}
super().__init__(**kwargs)

def recursively_remove_all_commands(self):
for command in self.commands.copy().values():
if isinstance(command, GroupMixin):
command.recursively_remove_all_commands()
self.remove_command(command.name)

def add_command(self, command):
"""Adds a :class:`Command` or its superclasses into the internal list
of commands.
Expand Down

0 comments on commit b87d5e5

Please sign in to comment.