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 reformat_file( filename: PathLike, config: FormateConfigDict, colour: ColourTrilean = None, ): """ Reformat the given file, and show the diff if changes were made. :param filename: The filename to reformat. :param config: The ``formate`` configuration, parsed from a TOML file (or similar). :param colour: Whether to force coloured output on (:py:obj:`True`) or off (:py:obj:`False`). .. latex:clearpage:: """ r = Reformatter(filename, config) with syntaxerror_for_file(filename): ret = r.run() if ret: click.echo(r.get_diff(), color=resolve_color_default(colour)) r.to_file() return ret
def make_recipe(out_dir: str = "./conda/"): """ Make a Conda ``meta.yaml`` recipe. """ # stdlib import warnings # 3rd party from consolekit.terminal_colours import Fore, resolve_color_default from domdf_python_tools.paths import PathPlus, traverse_to_file # this package from repo_helper import conda warnings.warn( "'repo-helper make-recipe' is deprecated. " "Please use 'mkrecipe' instead: https://mkrecipe.readthedocs.io/", DeprecationWarning, ) repo_dir = traverse_to_file(PathPlus.cwd(), "repo_helper.yml") recipe_file = PathPlus(out_dir).resolve() / "meta.yaml" recipe_file.parent.maybe_make() conda.make_recipe(repo_dir, recipe_file) click.echo(Fore.GREEN(f"Wrote recipe to {recipe_file!s}"), color=resolve_color_default())
def __init__( self, token: str, username: str, repo_name: str, *, managed_message="This file is managed by 'repo_helper'. Don't edit it directly.", verbose: bool = False, colour: ColourTrilean = True, ): self._tmpdir = tempfile.TemporaryDirectory() self.github = Github(token=token) self.verbose = verbose self.colour = resolve_color_default(colour) target_repo = PathPlus(self._tmpdir.name) config_file_name = "repo_helper.yml" github_repo: repos.Repository = self.github.repository(username, repo_name) contents_from_github: contents.Contents = github_repo.file_contents(config_file_name) (target_repo / config_file_name).write_bytes(contents_from_github.decoded) RepoHelper.__init__(self, target_repo, managed_message) self.load_settings()
def devenv( dest: PathLike = "venv", verbose: int = 0, colour: ColourTrilean = None, upgrade: bool = False, ): """ Create a virtualenv. """ # 3rd party from consolekit.terminal_colours import Fore, resolve_color_default from domdf_python_tools.paths import PathPlus # this package from repo_helper_devenv import mkdevenv ret = mkdevenv(PathPlus.cwd(), dest, verbose, upgrade=upgrade) if ret: sys.exit(ret) # pragma: no cover else: click.echo( Fore.GREEN("Successfully created development virtualenv."), color=resolve_color_default(colour), )
def main( dest: PathLike = "venv", verbose: int = 0, colour: ColourTrilean = None, show_traceback: bool = False, upgrade: bool = False, ): """ Create virtual environments using pyproject.toml metadata. """ # this package from pyproject_devenv import mkdevenv from pyproject_devenv.config import ConfigTracebackHandler with handle_tracebacks(show_traceback, ConfigTracebackHandler): ret = mkdevenv(PathPlus.cwd(), dest, verbosity=verbose, upgrade=upgrade) if ret: sys.exit(ret) # pragma: no cover else: click.echo( Fore.GREEN("Successfully created development virtualenv."), color=resolve_color_default(colour), )
def reformat( pyproject_file: "PathLike" = "pyproject.toml", encoder_class: str = "pyproject_parser:PyProjectTomlEncoder", parser_class: str = "pyproject_parser:PyProject", show_traceback: bool = False, show_diff: bool = False, colour: "ColourTrilean" = None, ): """ Reformat the given ``pyproject.toml`` file. """ # 3rd party from consolekit.terminal_colours import resolve_color_default # nodep from consolekit.utils import coloured_diff # nodep from domdf_python_tools.paths import PathPlus from toml import TomlEncoder pyproject_file = PathPlus(pyproject_file) click.echo(f"Reformatting {str(pyproject_file)!r}") with handle_tracebacks(show_traceback, CustomTracebackHandler): parser: Type[PyProject] = resolve_class(parser_class, "parser-class") encoder: Type[TomlEncoder] = resolve_class(encoder_class, "encoder-class") original_content: List[str] = pyproject_file.read_lines() config = parser.load(filename=pyproject_file, set_defaults=False) if config.project is not None and isinstance(config.project["name"], _NormalisedName): config.project["name"] = config.project["name"].unnormalized reformatted_content: List[str] = config.dump( filename=pyproject_file, encoder=encoder).split('\n') changed = reformatted_content != original_content if show_diff and changed: diff = coloured_diff( original_content, reformatted_content, str(pyproject_file), str(pyproject_file), "(original)", "(reformatted)", lineterm='', ) click.echo(diff, color=resolve_color_default(colour)) sys.exit(int(changed))
def show_cursor() -> None: """ Show the cursor. .. seealso:: The :func:`~.hidden_cursor` context manager. .. versionadded:: 0.7.0 """ click.echo( terminal_colours.Cursor.SHOW(), nl=False, color=terminal_colours.resolve_color_default(), )
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 hide_cursor() -> None: """ Hide the cursor. To show it again use :func:`~.show_cursor`, or use the :func:`~.hidden_cursor` context manager. .. versionadded:: 0.7.0 """ click.echo( terminal_colours.Cursor.HIDE(), nl=False, color=terminal_colours.resolve_color_default(), )
def abort(message: str, colour: ColourTrilean = None) -> Exception: """ Aborts the program execution. :param message: :param colour: Whether to use coloured output. Default auto-detect. :no-default colour: .. versionchanged:: 1.0.1 Added the ``colour`` option. """ click.echo(terminal_colours.Fore.RED(message), err=True, color=resolve_color_default(colour)) return click.Abort()
def __init__( self, token: str, target_repo: PathLike, managed_message="This file is managed by 'repo_helper'. Don't edit it directly.", *, verbose: bool = False, colour: ColourTrilean = True, ): super().__init__(target_repo, managed_message) self.github = Github(token=token) self.verbose = verbose self.colour = resolve_color_default(colour) self.load_settings()
def format_help_text(self, ctx: click.Context, formatter: click.formatting.HelpFormatter): """ Writes the help text to the formatter if it exists. :param ctx: :param formatter: """ doc = block_token.Document(self.help or '') with TerminalRenderer() as renderer: rendered_doc = indent(renderer.render(doc).strip(), " ") if resolve_color_default(self._colour) is False: # Also remove 'COMBINING LONG STROKE OVERLAY', used for strikethrough. rendered_doc = strip_ansi(rendered_doc).replace('̶', '') formatter.write('\n') formatter.write(rendered_doc) formatter.write('\n')
def reformat_file(filename: PathLike, yapf_style: str, isort_config_file: PathLike) -> int: """ Reformat the given file. :param filename: :param yapf_style: :param isort_config_file: """ isort_config = Config(settings_file=str(isort_config_file)) r = Reformatter(filename, yapf_style, isort_config) if r.run(): click.echo(r.get_diff(), color=resolve_color_default()) ret = 1 else: ret = 0 r.to_file() return ret
def main( filename: Iterable[PathLike], config_file: PathLike, exclude: "Optional[List[str]]", colour: "ColourTrilean" = None, verbose: bool = False, show_traceback: bool = False, show_diff: bool = False, ): """ Reformat the given Python source files. """ # stdlib import fnmatch import re # 3rd party from domdf_python_tools.paths import PathPlus # this package from formate.config import load_toml from formate.utils import SyntaxTracebackHandler, syntaxerror_for_file retv = 0 try: config = load_toml(config_file) except FileNotFoundError: raise click.UsageError(f"Config file '{config_file}' not found") for path in filename: for pattern in exclude or []: if re.match(fnmatch.translate(pattern), str(path)): continue path = PathPlus(path) if path.suffix not in {".py", ".pyi", ''} or path.is_dir(): if verbose >= 2: click.echo( f"Skipping {path} as it doesn't appear to be a Python file" ) continue r = Reformatter(path, config=config) with handle_tracebacks(show_traceback, cls=SyntaxTracebackHandler): with syntaxerror_for_file(path): ret_for_file = r.run() if ret_for_file: if verbose: click.echo(f"Reformatting {path}") if show_diff: click.echo(r.get_diff(), color=resolve_color_default(colour)) r.to_file() elif verbose >= 2: click.echo(f"Checking {path}") retv |= ret_for_file sys.exit(retv)
def main( module: Iterable[str] = (), config_file: PathLike = "pyproject.toml", colour: ColourTrilean = None, verbose: bool = False, show: Optional[bool] = None, count: Optional[bool] = None, ) -> None: """ Check modules can be imported. Modules can be given as the MODULE argument or in the configuration file. """ echo = functools.partial(click.echo, color=resolve_color_default(colour)) if module: if module == ('-', ): modules_to_check = list( filter(bool, map(str.strip, re.split("[\n ]", sys.stdin.read())))) else: modules_to_check = list(module) try: config = load_toml(config_file) except (KeyError, FileNotFoundError): config = {} else: try: config = load_toml(config_file) except KeyError as e: if e.args and e.args[ 0] == "No such table 'importcheck' or 'tool.importcheck'": click.echo(f"KeyError: {e.args[0]} in {config_file!r}", err=True) raise click.Abort() else: raise e modules_to_check = evaluate_markers(config) if "config" in config: if show is None: show = config["config"].get("show", show) if count is None: count = config["config"].get("count", count) if verbose == 2: show = True # if / in path replace with . and remove .py* extension modules_to_check = list(paths_to_modules(*modules_to_check)) if not modules_to_check: if verbose: echo("No modules to check.") sys.exit(0) about(2 if verbose else 1) click.echo() checker = ImportChecker(modules_to_check, show=show or False, colour=colour or False) retv = functools.reduce( operator.or_, map(operator.itemgetter(1), checker.check_modules()), 0) if (retv and not show) or count: echo() if count: echo(checker.format_statistics()) if retv and not show: echo("Tip: run with '--show' to show tracebacks for failed imports.") sys.exit(retv)