Browse Source

[commands] Allow relative paths when handling extensions

pull/6468/head
Kaylynn Morgan 4 years ago
committed by GitHub
parent
commit
1cbc537734
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 40
      discord/ext/commands/bot.py

40
discord/ext/commands/bot.py

@ -624,7 +624,13 @@ class BotBase(GroupMixin):
else: else:
self.__extensions[key] = lib self.__extensions[key] = lib
def load_extension(self, name): def _resolve_name(self, name, package):
try:
return importlib.util.resolve_name(name, package)
except ImportError:
raise errors.ExtensionNotFound(name)
def load_extension(self, name, *, package=None):
"""Loads an extension. """Loads an extension.
An extension is a python module that contains commands, cogs, or An extension is a python module that contains commands, cogs, or
@ -640,11 +646,19 @@ class BotBase(GroupMixin):
The extension name to load. It must be dot separated like The extension name to load. It must be dot separated like
regular Python imports if accessing a sub-module. e.g. regular Python imports if accessing a sub-module. e.g.
``foo.test`` if you want to import ``foo/test.py``. ``foo.test`` if you want to import ``foo/test.py``.
package: Optional[:class:`str`]
The package name to resolve relative imports with.
This is required when loading an extension using a relative path, e.g ``.foo.test``.
Defaults to ``None``.
.. versionadded:: 1.7
Raises Raises
-------- --------
ExtensionNotFound ExtensionNotFound
The extension could not be imported. The extension could not be imported.
This is also raised if the name of the extension could not
be resolved using the provided ``package`` parameter.
ExtensionAlreadyLoaded ExtensionAlreadyLoaded
The extension is already loaded. The extension is already loaded.
NoEntryPointError NoEntryPointError
@ -653,6 +667,7 @@ class BotBase(GroupMixin):
The extension or its setup function had an execution error. The extension or its setup function had an execution error.
""" """
name = self._resolve_name(name, package)
if name in self.__extensions: if name in self.__extensions:
raise errors.ExtensionAlreadyLoaded(name) raise errors.ExtensionAlreadyLoaded(name)
@ -662,7 +677,7 @@ class BotBase(GroupMixin):
self._load_from_module_spec(spec, name) self._load_from_module_spec(spec, name)
def unload_extension(self, name): def unload_extension(self, name, *, package=None):
"""Unloads an extension. """Unloads an extension.
When the extension is unloaded, all commands, listeners, and cogs are When the extension is unloaded, all commands, listeners, and cogs are
@ -679,13 +694,23 @@ class BotBase(GroupMixin):
The extension name to unload. It must be dot separated like The extension name to unload. It must be dot separated like
regular Python imports if accessing a sub-module. e.g. regular Python imports if accessing a sub-module. e.g.
``foo.test`` if you want to import ``foo/test.py``. ``foo.test`` if you want to import ``foo/test.py``.
package: Optional[:class:`str`]
The package name to resolve relative imports with.
This is required when unloading an extension using a relative path, e.g ``.foo.test``.
Defaults to ``None``.
.. versionadded:: 1.7
Raises Raises
------- -------
ExtensionNotFound
The name of the extension could not
be resolved using the provided ``package`` parameter.
ExtensionNotLoaded ExtensionNotLoaded
The extension was not loaded. The extension was not loaded.
""" """
name = self._resolve_name(name, package)
lib = self.__extensions.get(name) lib = self.__extensions.get(name)
if lib is None: if lib is None:
raise errors.ExtensionNotLoaded(name) raise errors.ExtensionNotLoaded(name)
@ -693,7 +718,7 @@ class BotBase(GroupMixin):
self._remove_module_references(lib.__name__) self._remove_module_references(lib.__name__)
self._call_module_finalizers(lib, name) self._call_module_finalizers(lib, name)
def reload_extension(self, name): def reload_extension(self, name, *, package=None):
"""Atomically reloads an extension. """Atomically reloads an extension.
This replaces the extension with the same extension, only refreshed. This is This replaces the extension with the same extension, only refreshed. This is
@ -707,6 +732,12 @@ class BotBase(GroupMixin):
The extension name to reload. It must be dot separated like The extension name to reload. It must be dot separated like
regular Python imports if accessing a sub-module. e.g. regular Python imports if accessing a sub-module. e.g.
``foo.test`` if you want to import ``foo/test.py``. ``foo.test`` if you want to import ``foo/test.py``.
package: Optional[:class:`str`]
The package name to resolve relative imports with.
This is required when reloading an extension using a relative path, e.g ``.foo.test``.
Defaults to ``None``.
.. versionadded:: 1.7
Raises Raises
------- -------
@ -714,12 +745,15 @@ class BotBase(GroupMixin):
The extension was not loaded. The extension was not loaded.
ExtensionNotFound ExtensionNotFound
The extension could not be imported. The extension could not be imported.
This is also raised if the name of the extension could not
be resolved using the provided ``package`` parameter.
NoEntryPointError NoEntryPointError
The extension does not have a setup function. The extension does not have a setup function.
ExtensionFailed ExtensionFailed
The extension setup function had an execution error. The extension setup function had an execution error.
""" """
name = self._resolve_name(name, package)
lib = self.__extensions.get(name) lib = self.__extensions.get(name)
if lib is None: if lib is None:
raise errors.ExtensionNotLoaded(name) raise errors.ExtensionNotLoaded(name)

Loading…
Cancel
Save