Skip to content

Commit

Permalink
Improve the exceptions raised on error
Browse files Browse the repository at this point in the history
  • Loading branch information
domdfcoding committed Apr 6, 2021
1 parent a12cdfe commit 15abdc4
Show file tree
Hide file tree
Showing 17 changed files with 608 additions and 78 deletions.
6 changes: 0 additions & 6 deletions doc-source/api.rst

This file was deleted.

6 changes: 6 additions & 0 deletions doc-source/api/exceptions.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
=====================================
:mod:`repo_helper_github.exceptions`
=====================================

.. automodule:: repo_helper_github.exceptions
:member-order: bysource
5 changes: 5 additions & 0 deletions doc-source/api/options.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
===================================
:mod:`repo_helper_github.options`
===================================

.. automodule:: repo_helper_github.options
6 changes: 6 additions & 0 deletions doc-source/api/repo_helper_github.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
==========================
:mod:`repo_helper_github`
==========================

.. automodule:: repo_helper_github
:exclude-members: github_command
5 changes: 2 additions & 3 deletions doc-source/contributing.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
==============
Contributing
==============
Overview
---------

.. This file based on https://github.com/PyGithub/PyGithub/blob/master/CONTRIBUTING.md
Expand Down
18 changes: 17 additions & 1 deletion doc-source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ Installation

.. end installation
Contents
-----------

.. toctree::
:hidden:

Expand All @@ -131,9 +134,22 @@ Installation
.. toctree::
:maxdepth: 3
:caption: Documentation
:glob:

usage
api

.. toctree::
:maxdepth: 3
:caption: API Reference
:glob:

api/repo_helper_github
api/*

.. toctree::
:maxdepth: 3
:caption: Contributing

contributing
Source

Expand Down
4 changes: 1 addition & 3 deletions repo_helper.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ short_desc: "Manage GitHub repositories with repo-helper."
use_whey: true
enable_conda: False
min_coverage: 85
sphinx_html_theme: furo

entry_points:
repo_helper.command:
Expand All @@ -38,9 +39,6 @@ intersphinx_mapping:
- '"github3": ("https://github3py.readthedocs.io/en/master/", None)'
- "'click': ('https://click.palletsprojects.com/en/7.x/', None)"

sphinx_html_theme: furo
standalone_contrib_guide: true

additional_ignore:
- update_all.py
- auto_merge.py
Expand Down
112 changes: 65 additions & 47 deletions repo_helper_github/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import click
from consolekit.input import confirm
from consolekit.terminal_colours import ColourTrilean, Fore, resolve_color_default
from consolekit.utils import abort
from deprecation_alias import deprecated
from domdf_python_tools.paths import PathPlus
from domdf_python_tools.typing import PathLike
Expand All @@ -58,6 +57,13 @@
from repo_helper_github._github import Github
from repo_helper_github._types import _EditKwargs
from repo_helper_github.cli import github_command
from repo_helper_github.exceptions import (
BadUsername,
ErrorCreatingRepository,
NoSuchBranch,
NoSuchRepository,
OrganizationError
)
from repo_helper_github.secret_validation import no_op_validator, validate_pypi_token

__author__: str = "Dominic Davis-Foster"
Expand Down Expand Up @@ -156,9 +162,11 @@ def new(self, org: bool = False) -> int:
"""
Create a new GitHub repository for this project.
:param org: Whether the repository should be created for the organisation set as ``username``,
:param org: Whether the repository should be created for the organization set as ``username``,
or for the authenticated user (default).
:rtype:
.. versionchanged:: 0.3.0
Removed the ``verbose`` option. Provide it to the class constructor instead.
Expand All @@ -178,7 +186,7 @@ def new(self, org: bool = False) -> int:
repo = self.github.create_repository(repo_name, **self.get_repo_kwargs())

if repo is None:
raise abort(f"No such repository {repo_name} for {'org' if org else 'user'} {user.login}.")
raise ErrorCreatingRepository(user.login, repo_name, org=org)

self.update_topics(repo)
click.echo(f"Success! View the repository online at {repo.html_url}")
Expand All @@ -201,9 +209,11 @@ def update(self, org: bool = False) -> int:
"""
Update the GitHub repository for this project.
:param org: Whether the repository should be created for the organisation set as ``username``,
:param org: Whether the repository should be created for the organization set as ``username``,
or for the authenticated user (default).
:rtype:
.. versionchanged:: 0.3.0
Removed the ``verbose`` option. Provide it to the class constructor instead.
Expand All @@ -214,10 +224,7 @@ def update(self, org: bool = False) -> int:
with self.echo_rate_limit():
user = self.get_org_or_user(org)
repo_name = self.templates.globals["repo_name"]
repo: Optional[repos.Repository] = self.github.repository(user.login, repo_name)

if repo is None:
raise abort(f"No such repository {repo_name} for {'org' if org else 'user'} {user.login}.")
repo: repos.Repository = self._get_repository(user, repo_name, org)

# TODO: add config option for allow_merge_commit

Expand All @@ -232,6 +239,17 @@ def update(self, org: bool = False) -> int:

return 0

def _get_repository(self, user: users.User, repository: str, org: bool) -> repos.Repository:
try:
repo: Optional[repos.Repository] = self.github.repository(user.login, repository)
except NotFoundError:
repo = None

if repo is None:
raise NoSuchRepository(user.login, repository, org=org)

return repo

def get_org_or_user(self, org: bool = False) -> Union[orgs.Organization, users.User]:
"""
If ``org`` is :py:obj:`True`, returns the :class:`~github3.orgs.Organization` object representing the
Expand All @@ -240,9 +258,9 @@ def get_org_or_user(self, org: bool = False) -> Union[orgs.Organization, users.U
If ``org`` is :py:obj:`False`, returns the :class:`~github3.users.AuthenticatedUser` object representing the
GitHub user that owns the repository.
:param org:
.. versionadded:: 0.3.0
:param org:
""" # noqa: D400

user = _utils_get_user(self.github)
Expand All @@ -264,25 +282,24 @@ def secrets(
"""
Set or update the secrets of the GitHub repository for this project.
:param org: Whether the repository should be created for the organisation set as ``username``,
.. versionadded:: 0.3.0
:param org: Whether the repository should be created for the organization set as ``username``,
or for the authenticated user (default).
:param overwrite: Overwrite existing values.
:default overwrite: ask first.
``PYPI_TOKEN`` and ``ANACONDA_TOKEN`` can either be passed as keyword arguments to this function or provided at the interactive prompt.
.. versionadded:: 0.3.0
:rtype:
.. versionchanged:: 0.4.0 Add ``overwrite``, ``PYPI_TOKEN``, ``ANACONDA_TOKEN`` options.
"""

with self.echo_rate_limit():
user = self.get_org_or_user(org)
repo_name = self.templates.globals["repo_name"]

repo: Optional[repos.Repository] = self.github.repository(user.login, repo_name)

if repo is None:
raise abort(f"No such repository {repo_name} for {'org' if org else 'user'} {user.login}.")
repo: repos.Repository = self._get_repository(user, repo_name, org)

# List of existing secrets.
existing_secrets = secrets.get_secrets(repo)
Expand Down Expand Up @@ -339,27 +356,26 @@ def protect_branch(self, branch: str, org: bool = False) -> int:
This requires that the Linux and Windows tests pass, together with the mypy check.
.. versionadded:: 0.4.0
:param branch: The branch to update protection for.
:param org: Whether the repository should be created for the organisation set as ``username``,
:param org: Whether the repository should be created for the organization set as ``username``,
or for the authenticated user (default).
:raises: :exc:`github3.exceptions.NotFoundError` if the branch is not found.
:raises:
.. versionadded:: 0.4.0
* :exc:`~.NoSuchBranch` if the branch is not found.
* :exc:`~.NoSuchRepository` if the repository is not found.
"""

with self.echo_rate_limit():
user = self.get_org_or_user(org)
repo_name = self.templates.globals["repo_name"]

repo: Optional[repos.Repository] = self.github.repository(user.login, repo_name)

if repo is None:
raise abort(f"No such repository {repo_name} for {'org' if org else 'user'} {user.login}.")
repo: repos.Repository = self._get_repository(user, repo_name, org)

gh_branch: Optional[Branch] = repo.branch(branch)
if not gh_branch:
raise NotFoundError
raise NoSuchBranch(user.login, repo_name, branch)

required_checks = list(compile_required_checks(self))

Expand All @@ -378,28 +394,34 @@ def assert_matching_usernames(self, user: users.User):
:param user:
"""

if user.login != self.templates.globals["username"]:
raise abort(
f"The username configured in 'repo_helper.yml' ({self.templates.globals['username']}) "
username = self.templates.globals["username"]

if user.login != username:
raise BadUsername(
f"The username configured in 'repo_helper.yml' ({username}) "
f"differs from that of the authenticated user ({user.login})!\n"
f"If {self.templates.globals['username']!r} is an organisation you should use the --org flag."
f"If {self.templates.globals['username']!r} is an organization you should use the --org flag.",
username=username,
)

def assert_org_member(self, user: users.User):
"""
Assert that the organisation configured in ``repo_helper.yml`` exists, and the authenticated user is a member.
Assert that the organization configured in ``repo_helper.yml`` exists, and the authenticated user is a member.
:param user:
"""

username = self.templates.globals["username"]

def error():
raise abort(
f"Either the organisation configured in 'repo_helper.yml' ({self.templates.globals['username']}) "
f"does not exist or the authenticated user ({user.login}) is not a member!"
raise OrganizationError(
f"Either the organization configured in 'repo_helper.yml' ({username}) "
f"does not exist or the authenticated user ({user.login}) is not a member!",
username,
)

try:
org = self.github.organization(self.templates.globals["username"])
org = self.github.organization(username)
except NotFoundError:
raise error()

Expand Down Expand Up @@ -442,19 +464,16 @@ def create_labels(self, org: bool = False) -> int:
"""
Create labels for this repository.
:param org: Whether the repository should be created for the organisation set as ``username``,
or for the authenticated user (default).
.. versionadded:: 0.5.0
:param org: Whether the repository should be created for the organization set as ``username``,
or for the authenticated user (default).
"""

with self.echo_rate_limit():
user = self.get_org_or_user(org)
repo_name = self.templates.globals["repo_name"]
repo: Optional[repos.Repository] = self.github.repository(user.login, repo_name)

if repo is None:
raise abort(f"No such repository {repo_name} for {'org' if org else 'user'} {user.login}.")
repo: repos.Repository = self._get_repository(user, repo_name, org)

current_labels = {label.name: label for label in repo.labels()}

Expand Down Expand Up @@ -489,9 +508,9 @@ def compile_required_checks(repo: RepoHelper) -> Iterator[str]:
"""
Returns an iterator over the names of required checks for the given repository.
:param repo:
.. versionadded:: 0.4.0
:param repo:
"""

actions_manager = ActionsManager(repo.target_repo, repo.templates)
Expand Down Expand Up @@ -532,15 +551,14 @@ class IsolatedGitHubManager(GitHubManager):
Subclass of :class:`~.GitHubManager` which can be used isolated from the repository
and its ``repo_helper.yml`` config file.
:param token: The token to authenticate with the GitHub API.
.. versionadded:: 0.4.0
:param token: The token to authenticate with the GitHub API.
:param username: The username of the GitHub account hosting the repository.
:param repo_name: The name of GitHub repository.
:param managed_message: Message placed at the top of files to indicate that they are managed by ``repo_helper``.
:param verbose: Whether to show information on the GitHub API rate limit.
:param colour: Whether to use coloured output.
.. versionadded:: 0.4.0
""" # noqa: D400

def __init__(
Expand Down
Loading

0 comments on commit 15abdc4

Please sign in to comment.