def requirement(requirement: str, file: Optional[str] = None) -> int: """ Add a requirement. """ # 3rd party from consolekit.utils import abort from domdf_python_tools.paths import PathPlus, traverse_to_file from domdf_python_tools.stringlist import StringList from packaging.requirements import InvalidRequirement from packaging.specifiers import SpecifierSet from shippinglabel import normalize_keep_dot from shippinglabel.requirements import ComparableRequirement, combine_requirements, read_requirements repo_dir: PathPlus = traverse_to_file(PathPlus.cwd(), "repo_helper.yml", "git_helper.yml") if file is None: requirements_file = repo_dir / "requirements.txt" if not requirements_file.is_file(): raise abort(f"'{file}' not found.") else: requirements_file = PathPlus(file) if not requirements_file.is_file(): raise abort("'requirements.txt' not found.") try: req = ComparableRequirement(requirement) except InvalidRequirement as e: raise BadRequirement(requirement, e) response = (PYPI_API / req.name / "json/").get() if response.status_code != 200: raise click.BadParameter(f"No such project {req.name}") else: req.name = normalize(response.json()["info"]["name"]) if not req.specifier: req.specifier = SpecifierSet( f">={response.json()['info']['version']}") click.echo(f"Adding requirement '{req}'") requirements, comments, invalid_lines = read_requirements( req_file=requirements_file, include_invalid=True, normalize_func=normalize_keep_dot, ) requirements.add(req) buf = StringList([*comments, *invalid_lines]) buf.extend(str(req) for req in sorted(combine_requirements(requirements))) requirements_file.write_lines(buf) return 0
def handle_ImportError(self, e: ImportError) -> bool: # 3rd party from consolekit.utils import abort # nodep raise abort( f"{e.__class__.__name__}: {e}\nUse '--traceback' to view the full traceback.", colour=False)
def log(entries: Optional[int] = None, reverse: bool = False, from_date: Optional[datetime] = None, from_tag: Optional[str] = None, colour: Optional[bool] = None, no_pager: bool = False) -> int: """ Show git commit log. """ # 3rd party from consolekit.terminal_colours import resolve_color_default from consolekit.utils import abort from domdf_python_tools.paths import PathPlus from southwark.log import Log from southwark.repo import Repo repo = Repo(PathPlus.cwd()) try: commit_log = Log(repo).log(max_entries=entries, reverse=reverse, from_date=from_date, from_tag=from_tag) except ValueError as e: raise abort(f"ERROR: {e}") if no_pager: click.echo(commit_log, color=resolve_color_default(colour)) else: click.echo_via_pager(commit_log, color=resolve_color_default(colour)) return 0
def main( what: str, name: str = "origin", username: Optional[str] = None, repo: Optional[str] = None, ): """ Toggle Git remotes between https and ssh. """ toggler = get_repo_or_raise() try: current_remote = Remote.from_url(toggler.get_current_remote(name)) except ValueError as e: raise abort(str(e)) current_remote.set_username(username) current_remote.set_repo(repo) if what.startswith("http"): current_remote.style = "https" elif what.startswith("ssh"): current_remote.style = "ssh" toggler.set_current_remote(current_remote, name) return 0
def list_remotes_callback(ctx: click.Context, param: click.Option, value: int): """ Callback fore the ``--list`` option. :param ctx: :param param: :param value: """ if not value or ctx.resilient_parsing: return toggler = get_repo_or_raise() remotes = toggler.list_remotes() if not remotes: raise abort("No remotes set!") longest_name = max(len(x) for x in remotes) for entry in remotes.items(): click.echo( f"{entry[0]}{' ' * (longest_name - len(entry[0]))} {entry[1]}") ctx.exit()
def handle_FileNotFoundError(self, e: FileNotFoundError) -> bool: # noqa: D102 # this package from consolekit.utils import abort raise abort(f"File Not Found: {e}", colour=False)
def bump(self, new_version: Version, commit: Optional[bool], message: str): """ Bump to the given version. :param new_version: :param commit: Whether to commit automatically (:py:obj:`True`) or ask first (:py:obj:`None`). :param message: The commit message. .. versionchanged:: 2021.8.11 Now takes a :class:`packaging.version.Version` rather than a :class:`domdf_python_tools.versions.Version`. """ new_version_str = str(new_version) dulwich_repo = Repo(self.repo.target_repo) if f"v{new_version_str}".encode("UTF-8") in dulwich_repo.refs.as_dict(b"refs/tags"): raise abort(f"The tag 'v{new_version_str}' already exists!") bumpversion_config = self.get_bumpversion_config(str(self.current_version), new_version_str) changed_files = [self.bumpversion_file.relative_to(self.repo.target_repo).as_posix()] for filename in bumpversion_config.keys(): if not os.path.isfile(filename): raise FileNotFoundError(filename) for filename, config in bumpversion_config.items(): self.bump_version_for_file(filename, config) changed_files.append(filename) # Update number in .bumpversion.cfg bv = ConfigUpdater() bv.read(self.bumpversion_file) bv["bumpversion"]["current_version"] = new_version_str self.bumpversion_file.write_clean(str(bv)) commit_message = message.format(current_version=self.current_version, new_version=new_version) click.echo(commit_message) if commit_changed_files( self.repo.target_repo, managed_files=changed_files, commit=commit, message=commit_message.encode("UTF-8"), enable_pre_commit=False, ): tag_create(dulwich_repo, f"v{new_version_str}")
def handle(self, e: BaseException) -> bool: """ Handle the given exception. :param e: """ # this package from consolekit.utils import abort exception_name = e.__class__.__name__ if hasattr(self, f"handle_{exception_name}"): return getattr(self, f"handle_{exception_name}")(e) for base in e.__class__.__mro__: if hasattr(self, f"handle_{base.__name__}"): return getattr(self, f"handle_{base.__name__}")(e) raise abort(f"An error occurred: {e}", colour=False)
def changelog( entries: Optional[int] = None, reverse: bool = False, colour: Optional[bool] = None, no_pager: bool = False, ): """ Show commits since the last version tag. """ # 3rd party from consolekit.terminal_colours import resolve_color_default from consolekit.utils import abort from domdf_python_tools.paths import PathPlus from southwark.log import Log from southwark.repo import Repo # this package from repo_helper.core import RepoHelper rh = RepoHelper(PathPlus.cwd()) rh.load_settings(allow_unknown_keys=True) repo = Repo(rh.target_repo) try: commit_log = Log(repo).log( max_entries=entries, reverse=reverse, from_tag=f"v{rh.templates.globals['version']}", ) except ValueError as e: raise abort(f"ERROR: {e}") if no_pager: click.echo(commit_log, color=resolve_color_default(colour)) else: click.echo_via_pager(commit_log, color=resolve_color_default(colour))
def handle_OrganizationError(self, e: OrganizationError) -> bool: # noqa: D102 raise abort(f"Organization Error: {e}", colour=False)
def handle_BadUsername(self, e: BadUsername) -> bool: # noqa: D102 raise abort(f"Bad Username: {e}", colour=False)
def handle_NoSuchBranch(self, e: NoSuchBranch) -> bool: # noqa: D102 raise abort(f"No Such Branch: {e}", colour=False)
def handle_NoSuchRepository(self, e: NoSuchRepository) -> bool: # noqa: D102 raise abort(f"No Such Repository: {e}", colour=False)
def handle_ErrorCreatingRepository( self, e: ErrorCreatingRepository) -> bool: # noqa: D102 raise abort(f"Error Creating Repository: {e}", colour=False)
def run_repo_helper( path, force: bool, initialise: bool, commit: Optional[bool], message: str, enable_pre_commit: bool = True, ) -> int: """ Run repo_helper. :param path: The repository path. :param force: Whether to force the operation if the repository is not clean. :param initialise: Whether to initialise the repository. :param commit: Whether to commit unchanged files. :param message: The commit message. :param enable_pre_commit: Whether to install and configure pre-commit. Default :py:obj`True`. """ # this package from repo_helper.cli.commands.init import init_repo from repo_helper.core import RepoHelper from repo_helper.utils import easter_egg try: rh = RepoHelper(path) rh.load_settings() except FileNotFoundError as e: error_block = textwrap.indent(str(e), '\t') raise abort( f"Unable to run 'repo_helper'.\nThe error was:\n{error_block}") if not assert_clean(rh.target_repo, allow_config=("repo_helper.yml", "git_helper.yml")): if force: click.echo(Fore.RED("Proceeding anyway"), err=True) else: return 1 if initialise: r = Repo(rh.target_repo) for filename in init_repo(rh.target_repo, rh.templates): r.stage(os.path.normpath(filename)) managed_files = rh.run() try: commit_changed_files( repo_path=rh.target_repo, managed_files=managed_files, commit=commit, message=message.encode("UTF-8"), enable_pre_commit=enable_pre_commit, ) except CommitError as e: indented_error = '\n'.join(f"\t{line}" for line in textwrap.wrap(str(e))) click.echo( f"Unable to commit changes. The error was:\n\n{indented_error}", err=True) return 1 easter_egg() return 0
def handle_TypeError(self, e: TypeError) -> bool: # noqa: D102 raise abort(f"{e.__class__.__name__}: {e}", colour=False)
def handle_BadConfigError(self, e: "BadConfigError") -> bool: # noqa: D102 raise abort(f"{e.__class__.__name__}: {e}", colour=False)
def handle_BaseInstallError(self, e: "BaseInstallError") -> bool: # noqa: D102 # pragma: no cover raise abort(f"Error: {e}", colour=False)