Source code for octocheese.__main__

#!/usr/bin/env python3
#
#  __main__.py
"""
Entry points when running as a script.
"""
#
#  Copyright (c) 2020-2021 Dominic Davis-Foster <dominic@davis-foster.co.uk>
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#

# stdlib
import sys
from typing import Union

# 3rd party
import click
from apeye_core import URL
from click import Context, Option
from consolekit import click_command
from consolekit.options import auto_default_option, flag_option, version_option
from domdf_python_tools.secrets import Secret
from github3_utils.click import token_option

__all__ = ["main", "run", "token_var"]

token_var = "GITHUB_TOKEN"


def _version_callback(ctx: Context, param: Option, value: int):
	# this package
	from octocheese import __version__

	if not value or ctx.resilient_parsing:
		return

	print(f"octocheese version {__version__}")
	sys.exit(0)


@version_option(_version_callback)
@flag_option(
		"--no-self-promotion",
		help="Don't show information about OctoCheese at the bottom of the release message.",
		)
@flag_option("-T", "--traceback", help="Show the full traceback on error.")
@auto_default_option(
		"-n",
		"--max-tags",
		type=click.INT,
		help="The maximum number of tags to process, starting with the most recent.",
		show_default=True,
		)
@auto_default_option(
		"-r",
		"--repo",
		type=click.STRING,
		help="The repository name (in the format <username>/<repository>) or the complete GitHub URL.",
		)
@token_option(token_var)
@click.argument("pypi_name", type=click.STRING)
@click_command()
def main(
		pypi_name: str,
		token: str,
		repo: Union[str, URL, None] = None,
		no_self_promotion: bool = False,
		max_tags: int = -1,
		traceback: bool = False,
		):
	"""
	Copy PyPI Packages to GitHub Releases.
	"""

	# 3rd party
	import click
	import dulwich.errors
	from consolekit.utils import abort
	from dulwich.repo import Repo
	from github3.exceptions import AuthenticationFailed

	gh_token = Secret(token)

	if repo is None:
		try:
			config = Repo('.').get_config()
			repo = URL(config.get(("remote", "origin"), "url").decode("UTF-8"))
		except dulwich.errors.NotGitRepository as e:
			raise click.UsageError(str(e))
	else:
		repo = URL(repo)

	if repo.suffix == ".git":
		repo = repo.with_suffix('')

	repo_name = repo.name

	# first case is for full url, second for github/hello_world
	github_username = repo.parent.name or repo.domain.domain

	try:
		run(
				gh_token,
				github_username,
				repo_name,
				pypi_name,
				self_promotion=not no_self_promotion,
				max_tags=max_tags
				)
	except AuthenticationFailed:
		raise click.UsageError("Invalid credentials for GitHub REST API.")
	except Exception as e:  # pragma: no cover
		if traceback:
			raise
		else:
			raise abort(f"An error occurred: {e}")


[docs]def run( github_token: Secret, github_username: str, repo_name: str, pypi_name: str, self_promotion=True, max_tags: int = -1, ): """ Helper function for when running as script or action. :param github_token: The token to authenticate with the GitHub API with. See https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token for instructions on generating a token. :param github_username: The username of the GitHub account that owns the repository. :param repo_name: The name of the GitHub repository. :param pypi_name: The name of the package on PyPI. :param self_promotion: Show information about OctoCheese at the bottom of the release message. :param max_tags: The maximum number of tags to process, starting with the most recent. Set to ``-1`` to process all tags. .. versionchanged:: 0.1.0 Added the ``self_promotion`` option. .. versionchanged:: 0.3.0 Added the ``max_tags`` option. """ # 3rd party from github3 import GitHub from github3_utils import echo_rate_limit # this package from octocheese.core import copy_pypi_2_github g = GitHub(token=github_token.value) click.echo(f"Running for repo {github_username}/{repo_name}") with echo_rate_limit(g, True): copy_pypi_2_github( g, repo_name, github_username, pypi_name=pypi_name, self_promotion=self_promotion, max_tags=max_tags, )
if __name__ == "__main__": sys.exit(main())