mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-07 03:38:53 -05:00
[Docs] Update downloader framework docs (#914)
* Update installable * Update Repo manager
This commit is contained in:
parent
0ba6d9a5af
commit
c6762234e6
@ -1,3 +1,8 @@
|
|||||||
|
__all__ = ["DownloaderException", "GitException", "InvalidRepoName", "ExistingGitRepo",
|
||||||
|
"MissingGitRepo", "CloningError", "CurrentHashError", "HardResetError",
|
||||||
|
"UpdateError", "GitDiffError", "PipError"]
|
||||||
|
|
||||||
|
|
||||||
class DownloaderException(Exception):
|
class DownloaderException(Exception):
|
||||||
"""
|
"""
|
||||||
Base class for Downloader exceptions.
|
Base class for Downloader exceptions.
|
||||||
@ -14,7 +19,7 @@ class GitException(DownloaderException):
|
|||||||
class InvalidRepoName(DownloaderException):
|
class InvalidRepoName(DownloaderException):
|
||||||
"""
|
"""
|
||||||
Throw when a repo name is invalid. Check
|
Throw when a repo name is invalid. Check
|
||||||
the message for a more detailed reason.
|
the message for a more detailed reason.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -22,7 +27,7 @@ class InvalidRepoName(DownloaderException):
|
|||||||
class ExistingGitRepo(DownloaderException):
|
class ExistingGitRepo(DownloaderException):
|
||||||
"""
|
"""
|
||||||
Thrown when trying to clone into a folder where a
|
Thrown when trying to clone into a folder where a
|
||||||
git repo already exists.
|
git repo already exists.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -30,7 +35,7 @@ class ExistingGitRepo(DownloaderException):
|
|||||||
class MissingGitRepo(DownloaderException):
|
class MissingGitRepo(DownloaderException):
|
||||||
"""
|
"""
|
||||||
Thrown when a git repo is expected to exist but
|
Thrown when a git repo is expected to exist but
|
||||||
does not.
|
does not.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -45,7 +50,7 @@ class CloningError(GitException):
|
|||||||
class CurrentHashError(GitException):
|
class CurrentHashError(GitException):
|
||||||
"""
|
"""
|
||||||
Thrown when git returns a non zero exit code attempting
|
Thrown when git returns a non zero exit code attempting
|
||||||
to determine the current commit hash.
|
to determine the current commit hash.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -53,7 +58,7 @@ class CurrentHashError(GitException):
|
|||||||
class HardResetError(GitException):
|
class HardResetError(GitException):
|
||||||
"""
|
"""
|
||||||
Thrown when there is an issue trying to execute a hard reset
|
Thrown when there is an issue trying to execute a hard reset
|
||||||
(usually prior to a repo update).
|
(usually prior to a repo update).
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@ -18,42 +18,19 @@ class InstallableType(Enum):
|
|||||||
class Installable(RepoJSONMixin):
|
class Installable(RepoJSONMixin):
|
||||||
"""
|
"""
|
||||||
Base class for anything the Downloader cog can install.
|
Base class for anything the Downloader cog can install.
|
||||||
- Modules
|
- Modules
|
||||||
- Repo Libraries
|
- Repo Libraries
|
||||||
- Other stuff?
|
- Other stuff?
|
||||||
"""
|
"""
|
||||||
|
|
||||||
INFO_FILE_DESCRIPTION = """
|
INFO_FILE_DESCRIPTION = """
|
||||||
The info.json file may exist inside every package folder in the repo,
|
|
||||||
it is optional however. This string describes the valid keys within
|
|
||||||
an info file (and maybe how the Downloader cog uses them).
|
|
||||||
|
|
||||||
KEYS (case sensitive):
|
|
||||||
author (list of strings) - list of names of authors of the cog
|
|
||||||
bot_version (list of integer) - Min version number of Red in the
|
|
||||||
format (MAJOR, MINOR, PATCH)
|
|
||||||
description (string) - A long description of the cog that appears
|
|
||||||
when a user executes `!cog info`
|
|
||||||
hidden (bool) - Determines if a cog is available for install.
|
|
||||||
install_msg (string) - The message that gets displayed when a cog is
|
|
||||||
installed
|
|
||||||
required_cogs (map of cogname to repo URL) - A map of required cogs
|
|
||||||
that this cog depends on. Downloader will not deal with this
|
|
||||||
functionality but it may be useful for other cogs.
|
|
||||||
requirements (list of strings) - list of required libraries that are
|
|
||||||
passed to pip on cog install. SHARED_LIBRARIES do NOT go in this
|
|
||||||
list.
|
|
||||||
short (string) - A short description of the cog that appears when
|
|
||||||
a user executes `!cog list`
|
|
||||||
tags (list of strings) - A list of strings that are related to the
|
|
||||||
functionality of the cog. Used to aid in searching.
|
|
||||||
type (string) - Optional, defaults to COG. Must be either COG or
|
|
||||||
SHARED_LIBRARY. If SHARED_LIBRARY then HIDDEN will be True.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, location: Path):
|
def __init__(self, location: Path):
|
||||||
"""
|
"""
|
||||||
Base installable initializer.
|
Base installable initializer.
|
||||||
|
|
||||||
:param location: Location (file or folder) to the installable.
|
:param location: Location (file or folder) to the installable.
|
||||||
"""
|
"""
|
||||||
super().__init__(location)
|
super().__init__(location)
|
||||||
@ -90,9 +67,11 @@ class Installable(RepoJSONMixin):
|
|||||||
async def copy_to(self, target_dir: Path) -> bool:
|
async def copy_to(self, target_dir: Path) -> bool:
|
||||||
"""
|
"""
|
||||||
Copies this cog/shared_lib to the given directory. This
|
Copies this cog/shared_lib to the given directory. This
|
||||||
will overwrite any files in the target directory
|
will overwrite any files in the target directory.
|
||||||
:param target_dir: The installation directory to install to.
|
|
||||||
:return: bool - status of installation
|
:param pathlib.Path target_dir: The installation directory to install to.
|
||||||
|
:return: Status of installation
|
||||||
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
if self._location.is_file():
|
if self._location.is_file():
|
||||||
copy_func = shutil.copy2
|
copy_func = shutil.copy2
|
||||||
@ -120,7 +99,8 @@ class Installable(RepoJSONMixin):
|
|||||||
def _process_info_file(self, info_file_path: Path=None) -> MutableMapping[str, Any]:
|
def _process_info_file(self, info_file_path: Path=None) -> MutableMapping[str, Any]:
|
||||||
"""
|
"""
|
||||||
Processes an information file. Loads dependencies among other
|
Processes an information file. Loads dependencies among other
|
||||||
information into this object.
|
information into this object.
|
||||||
|
|
||||||
:type info_file_path:
|
:type info_file_path:
|
||||||
:param info_file_path: Optional path to information file, defaults to `self.__info_file`
|
:param info_file_path: Optional path to information file, defaults to `self.__info_file`
|
||||||
:return: Raw information dictionary
|
:return: Raw information dictionary
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import json
|
|||||||
import os
|
import os
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Tuple, MutableMapping
|
from typing import Tuple, MutableMapping, Union
|
||||||
from subprocess import run as sp_run, PIPE
|
from subprocess import run as sp_run, PIPE
|
||||||
from sys import executable
|
from sys import executable
|
||||||
import pkgutil
|
import pkgutil
|
||||||
@ -166,7 +166,8 @@ class Repo(RepoJSONMixin):
|
|||||||
async def clone(self) -> Tuple[str]:
|
async def clone(self) -> Tuple[str]:
|
||||||
"""
|
"""
|
||||||
Clones a new repo.
|
Clones a new repo.
|
||||||
:return: List of available modules from this repo.
|
|
||||||
|
:return: List of available module names from this repo.
|
||||||
"""
|
"""
|
||||||
exists, path = self._existing_git_repo()
|
exists, path = self._existing_git_repo()
|
||||||
if exists:
|
if exists:
|
||||||
@ -203,6 +204,7 @@ class Repo(RepoJSONMixin):
|
|||||||
async def current_branch(self) -> str:
|
async def current_branch(self) -> str:
|
||||||
"""
|
"""
|
||||||
Determines the current branch using git commands.
|
Determines the current branch using git commands.
|
||||||
|
|
||||||
:return: Current branch name
|
:return: Current branch name
|
||||||
"""
|
"""
|
||||||
exists, _ = self._existing_git_repo()
|
exists, _ = self._existing_git_repo()
|
||||||
@ -226,6 +228,7 @@ class Repo(RepoJSONMixin):
|
|||||||
async def current_commit(self, branch: str=None) -> str:
|
async def current_commit(self, branch: str=None) -> str:
|
||||||
"""
|
"""
|
||||||
Determines the current commit hash of the repo.
|
Determines the current commit hash of the repo.
|
||||||
|
|
||||||
:param branch: Override for repo's branch attribute
|
:param branch: Override for repo's branch attribute
|
||||||
:return: Commit hash string
|
:return: Commit hash string
|
||||||
"""
|
"""
|
||||||
@ -253,8 +256,8 @@ class Repo(RepoJSONMixin):
|
|||||||
async def hard_reset(self, branch: str=None) -> None:
|
async def hard_reset(self, branch: str=None) -> None:
|
||||||
"""
|
"""
|
||||||
Performs a hard reset on the current repo.
|
Performs a hard reset on the current repo.
|
||||||
|
|
||||||
:param branch: Override for repo branch attribute.
|
:param branch: Override for repo branch attribute.
|
||||||
:return:
|
|
||||||
"""
|
"""
|
||||||
if branch is None:
|
if branch is None:
|
||||||
branch = self.branch
|
branch = self.branch
|
||||||
@ -280,8 +283,9 @@ class Repo(RepoJSONMixin):
|
|||||||
async def update(self) -> (str, str):
|
async def update(self) -> (str, str):
|
||||||
"""
|
"""
|
||||||
Updates the current branch of this repo.
|
Updates the current branch of this repo.
|
||||||
:return: Old commit hash
|
|
||||||
:return: New commit hash
|
:return: tuple of (old commit hash, new commit hash)
|
||||||
|
:rtype: tuple
|
||||||
"""
|
"""
|
||||||
curr_branch = await self.current_branch()
|
curr_branch = await self.current_branch()
|
||||||
old_commit = await self.current_commit(branch=curr_branch)
|
old_commit = await self.current_commit(branch=curr_branch)
|
||||||
@ -308,9 +312,11 @@ class Repo(RepoJSONMixin):
|
|||||||
async def install_cog(self, cog: Installable, target_dir: Path) -> bool:
|
async def install_cog(self, cog: Installable, target_dir: Path) -> bool:
|
||||||
"""
|
"""
|
||||||
Copies a cog to the target directory.
|
Copies a cog to the target directory.
|
||||||
:param cog:
|
|
||||||
:param target_dir:
|
:param Installable cog: Cog to install.
|
||||||
:return: bool - if installation succeeded
|
:param pathlib.Path target_dir: Directory to install the cog in.
|
||||||
|
:return: Installation success status.
|
||||||
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
if cog not in self.available_cogs:
|
if cog not in self.available_cogs:
|
||||||
raise DownloaderException("That cog does not exist in this repo")
|
raise DownloaderException("That cog does not exist in this repo")
|
||||||
@ -326,10 +332,12 @@ class Repo(RepoJSONMixin):
|
|||||||
async def install_libraries(self, target_dir: Path, libraries: Tuple[Installable]=()) -> bool:
|
async def install_libraries(self, target_dir: Path, libraries: Tuple[Installable]=()) -> bool:
|
||||||
"""
|
"""
|
||||||
Copies all shared libraries (or a given subset) to the target
|
Copies all shared libraries (or a given subset) to the target
|
||||||
directory.
|
directory.
|
||||||
:param target_dir:
|
|
||||||
:param libraries: A subset of available libraries
|
:param pathlib.Path target_dir: Directory to install shared libraries to.
|
||||||
:return: bool - all copies succeeded
|
:param tuple(Installable) libraries: A subset of available libraries.
|
||||||
|
:return: Status of all installs.
|
||||||
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
if libraries:
|
if libraries:
|
||||||
if not all([i in self.available_libraries for i in libraries]):
|
if not all([i in self.available_libraries for i in libraries]):
|
||||||
@ -344,11 +352,13 @@ class Repo(RepoJSONMixin):
|
|||||||
async def install_requirements(self, cog: Installable, target_dir: Path) -> bool:
|
async def install_requirements(self, cog: Installable, target_dir: Path) -> bool:
|
||||||
"""
|
"""
|
||||||
Installs the requirements defined by the requirements
|
Installs the requirements defined by the requirements
|
||||||
attribute on the cog object and puts them in the given
|
attribute on the cog object and puts them in the given
|
||||||
target directory.
|
target directory.
|
||||||
:param cog:
|
|
||||||
:param target_dir:
|
:param Installable cog: Cog for which to install requirements.
|
||||||
:return:
|
:param pathlib.Path target_dir: Path to which to install requirements.
|
||||||
|
:return: Status of requirements install.
|
||||||
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
if not target_dir.is_dir():
|
if not target_dir.is_dir():
|
||||||
raise ValueError("Target directory is not a directory.")
|
raise ValueError("Target directory is not a directory.")
|
||||||
@ -359,10 +369,12 @@ class Repo(RepoJSONMixin):
|
|||||||
async def install_raw_requirements(self, requirements: Tuple[str], target_dir: Path) -> bool:
|
async def install_raw_requirements(self, requirements: Tuple[str], target_dir: Path) -> bool:
|
||||||
"""
|
"""
|
||||||
Installs a list of requirements using pip and places them into
|
Installs a list of requirements using pip and places them into
|
||||||
the given target directory.
|
the given target directory.
|
||||||
:param requirements:
|
|
||||||
:param target_dir:
|
:param tuple(str) requirements: List of requirement names to install via pip.
|
||||||
:return:
|
:param pathlib.Path target_dir: Directory to install requirements to.
|
||||||
|
:return: Status of all requirements install.
|
||||||
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
if len(requirements) == 0:
|
if len(requirements) == 0:
|
||||||
return True
|
return True
|
||||||
@ -388,7 +400,8 @@ class Repo(RepoJSONMixin):
|
|||||||
def available_cogs(self) -> Tuple[Installable]:
|
def available_cogs(self) -> Tuple[Installable]:
|
||||||
"""
|
"""
|
||||||
Returns a list of available cogs (not shared libraries and not hidden).
|
Returns a list of available cogs (not shared libraries and not hidden).
|
||||||
:return: tuple(installable)
|
|
||||||
|
:rtype: tuple(Installable)
|
||||||
"""
|
"""
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
return tuple(
|
return tuple(
|
||||||
@ -400,6 +413,8 @@ class Repo(RepoJSONMixin):
|
|||||||
def available_libraries(self) -> Tuple[Installable]:
|
def available_libraries(self) -> Tuple[Installable]:
|
||||||
"""
|
"""
|
||||||
Returns a list of available shared libraries in this repo.
|
Returns a list of available shared libraries in this repo.
|
||||||
|
|
||||||
|
:rtype: tuple(Installable)
|
||||||
"""
|
"""
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
return tuple(
|
return tuple(
|
||||||
@ -447,10 +462,12 @@ class RepoManager:
|
|||||||
async def add_repo(self, url: str, name: str, branch: str="master") -> Repo:
|
async def add_repo(self, url: str, name: str, branch: str="master") -> Repo:
|
||||||
"""
|
"""
|
||||||
Adds a repo and clones it.
|
Adds a repo and clones it.
|
||||||
:param url:
|
|
||||||
:param name:
|
:param url: URL of git repo to clone.
|
||||||
:param branch:
|
:param name: Internal name of repo.
|
||||||
:return:
|
:param branch: Branch to clone.
|
||||||
|
:return: New repo object representing cloned repo.
|
||||||
|
:rtype: Repo
|
||||||
"""
|
"""
|
||||||
name = self.validate_and_normalize_repo_name(name)
|
name = self.validate_and_normalize_repo_name(name)
|
||||||
if self.does_repo_exist(name):
|
if self.does_repo_exist(name):
|
||||||
@ -469,27 +486,31 @@ class RepoManager:
|
|||||||
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def get_repo(self, name: str) -> Repo:
|
def get_repo(self, name: str) -> Union[Repo, None]:
|
||||||
"""
|
"""
|
||||||
Returns a repo object with the given name.
|
Returns a repo object with the given name.
|
||||||
|
|
||||||
:param name: Repo name
|
:param name: Repo name
|
||||||
:return: Repo object or None
|
:return: Repo object or ``None`` if repo does not exist.
|
||||||
|
:rtype: Union[Repo, None]
|
||||||
"""
|
"""
|
||||||
return self._repos.get(name, None)
|
return self._repos.get(name, None)
|
||||||
|
|
||||||
def get_all_repo_names(self) -> Tuple[str]:
|
def get_all_repo_names(self) -> Tuple[str]:
|
||||||
"""
|
"""
|
||||||
Returns a tuple of all repo names
|
Returns a tuple of all repo names
|
||||||
:return:
|
|
||||||
|
:rtype: tuple(str)
|
||||||
"""
|
"""
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
return tuple(self._repos.keys())
|
return tuple(self._repos.keys())
|
||||||
|
|
||||||
async def delete_repo(self, name: str):
|
async def delete_repo(self, name: str):
|
||||||
"""
|
"""
|
||||||
Deletes a repo and its' folders with the given name.
|
Deletes a repo and its folders with the given name.
|
||||||
:param name:
|
|
||||||
:return:
|
:param name: Name of the repo to delete.
|
||||||
|
:raises MissingGitRepo: If the repo does not exist.
|
||||||
"""
|
"""
|
||||||
repo = self.get_repo(name)
|
repo = self.get_repo(name)
|
||||||
if repo is None:
|
if repo is None:
|
||||||
@ -506,10 +527,11 @@ class RepoManager:
|
|||||||
|
|
||||||
async def update_all_repos(self) -> MutableMapping[Repo, Tuple[str, str]]:
|
async def update_all_repos(self) -> MutableMapping[Repo, Tuple[str, str]]:
|
||||||
"""
|
"""
|
||||||
Calls repo.update() on all repos, returns a mapping of repos
|
Calls :py:meth:`Repo.update` on all repos.
|
||||||
that received new commits to a tuple containing old and
|
|
||||||
new commit hashes.
|
|
||||||
:return:
|
:return:
|
||||||
|
A mapping of :py:class:`Repo` objects that received new commits to a tuple containing old and
|
||||||
|
new commit hashes.
|
||||||
"""
|
"""
|
||||||
ret = {}
|
ret = {}
|
||||||
for _, repo in self._repos.items():
|
for _, repo in self._repos.items():
|
||||||
|
|||||||
@ -1,7 +1,45 @@
|
|||||||
.. downloader framework reference
|
.. downloader framework reference
|
||||||
|
|
||||||
Downloader Framework Reference
|
Downloader Framework
|
||||||
==============================
|
====================
|
||||||
|
|
||||||
|
Info.json
|
||||||
|
*********
|
||||||
|
|
||||||
|
The info.json file may exist inside every package folder in the repo,
|
||||||
|
it is optional however. This string describes the valid keys within
|
||||||
|
an info file (and maybe how the Downloader cog uses them).
|
||||||
|
|
||||||
|
KEYS (case sensitive):
|
||||||
|
|
||||||
|
- ``author`` (list of strings) - list of names of authors of the cog
|
||||||
|
|
||||||
|
- ``bot_version`` (list of integer) - Min version number of Red in the format ``(MAJOR, MINOR, PATCH)``
|
||||||
|
|
||||||
|
- ``description`` (string) - A long description of the cog that appears when a user executes ```!cog info``.
|
||||||
|
|
||||||
|
- ``hidden`` (bool) - Determines if a cog is available for install.
|
||||||
|
|
||||||
|
- ``install_msg`` (string) - The message that gets displayed when a cog is installed
|
||||||
|
|
||||||
|
- ``required_cogs`` (map of cogname to repo URL) - A map of required cogs that this cog depends on.
|
||||||
|
Downloader will not deal with this functionality but it may be useful for other cogs.
|
||||||
|
|
||||||
|
- ``requirements`` (list of strings) - list of required libraries that are
|
||||||
|
passed to pip on cog install. ``SHARED_LIBRARIES`` do NOT go in this
|
||||||
|
list.
|
||||||
|
|
||||||
|
- ``short`` (string) - A short description of the cog that appears when
|
||||||
|
a user executes `!cog list`
|
||||||
|
|
||||||
|
- ``tags`` (list of strings) - A list of strings that are related to the
|
||||||
|
functionality of the cog. Used to aid in searching.
|
||||||
|
|
||||||
|
- ``type`` (string) - Optional, defaults to ``COG``. Must be either ``COG`` or
|
||||||
|
``SHARED_LIBRARY``. If ``SHARED_LIBRARY`` then ``hidden`` will be ``True``.
|
||||||
|
|
||||||
|
API Reference
|
||||||
|
*************
|
||||||
|
|
||||||
.. automodule:: cogs.downloader.json_mixins
|
.. automodule:: cogs.downloader.json_mixins
|
||||||
|
|
||||||
@ -10,14 +48,29 @@ Downloader Framework Reference
|
|||||||
|
|
||||||
.. automodule:: cogs.downloader.installable
|
.. automodule:: cogs.downloader.installable
|
||||||
|
|
||||||
|
Installable
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
.. autoclass:: Installable
|
.. autoclass:: Installable
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. automodule:: cogs.downloader.repo_manager
|
.. automodule:: cogs.downloader.repo_manager
|
||||||
|
|
||||||
|
Repo
|
||||||
|
^^^^
|
||||||
|
|
||||||
.. autoclass:: Repo
|
.. autoclass:: Repo
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
Repo Manager
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
.. autoclass:: RepoManager
|
.. autoclass:: RepoManager
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
Exceptions
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
.. automodule:: cogs.downloader.errors
|
||||||
|
:members:
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user