better output for pycalver grep

This commit is contained in:
Manuel Barkhau 2020-10-04 20:43:37 +00:00
parent 8ab1644962
commit b466ca9d39
2 changed files with 52 additions and 30 deletions

View file

@ -110,7 +110,7 @@ def _validate_release_tag(tag: typ.Optional[str]) -> None:
@click.help_option() @click.help_option()
@click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.") @click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.")
def cli(verbose: int = 0) -> None: def cli(verbose: int = 0) -> None:
"""Automatically update PyCalVer version strings on python projects.""" """Automatically update PyCalVer version strings in all project files."""
_configure_logging(verbose=max(_VERBOSE, verbose)) _configure_logging(verbose=max(_VERBOSE, verbose))
@ -121,7 +121,7 @@ def cli(verbose: int = 0) -> None:
@click.option( @click.option(
"--release", "--release",
default=None, default=None,
metavar="<name>", metavar="<NAME>",
help=( help=(
f"Override release name of current_version. Valid options are: " f"Override release name of current_version. Valid options are: "
f"{', '.join(VALID_RELEASE_TAG_VALUES)}." f"{', '.join(VALID_RELEASE_TAG_VALUES)}."
@ -135,7 +135,7 @@ def cli(verbose: int = 0) -> None:
@click.option( @click.option(
"--date", "--date",
default=None, default=None,
metavar="<iso-date>", metavar="<ISODATE>",
help=f"Set explicit date in format YYYY-0M-0D (e.g. {_current_date}).", help=f"Set explicit date in format YYYY-0M-0D (e.g. {_current_date}).",
) )
def test( def test(
@ -179,11 +179,9 @@ def test(
click.echo(f"PEP440 : {pep440_version}") click.echo(f"PEP440 : {pep440_version}")
def _grep_text(pattern: patterns.Pattern, text: str, color: bool) -> int: def _grep_text(pattern: patterns.Pattern, text: str, color: bool) -> typ.Iterable[str]:
match_count = 0
all_lines = text.splitlines() all_lines = text.splitlines()
for match in pattern.regexp.finditer(text): for match in pattern.regexp.finditer(text):
match_count += 1
match_start, match_end = match.span() match_start, match_end = match.span()
line_idx = text[:match_start].count("\n") line_idx = text[:match_start].count("\n")
@ -212,12 +210,11 @@ def _grep_text(pattern: patterns.Pattern, text: str, color: bool) -> int:
else: else:
lines[1] = matched_line lines[1] = matched_line
print() prefixed_lines = [
f"{lines_offset + i:>4}: {line}"
for i, line in enumerate(lines): for i, line in enumerate(lines)
print(f"{lines_offset + i:>4}: {line}") ]
yield "\n".join(prefixed_lines)
return match_count
def _grep( def _grep(
@ -231,18 +228,21 @@ def _grep(
for file_io in file_ios: for file_io in file_ios:
text = file_io.read() text = file_io.read()
_match_count = _grep_text(pattern, text, color) match_strs = list(_grep_text(pattern, text, color))
if len(match_strs) > 0:
print(file_io.name)
for match_str in match_strs:
print(match_str)
print()
print() match_count += len(match_strs)
print(f"Found {_match_count} match for pattern '{raw_pattern}' in {file_io.name}")
print()
match_count += _match_count if match_count == 0:
logger.error(f"Pattern not found: '{raw_pattern}'")
if match_count == 0 or _VERBOSE: if match_count == 0 or _VERBOSE:
pyexpr_regex = regexfmt.pyexpr_regex(pattern.regexp.pattern) pyexpr_regex = regexfmt.pyexpr_regex(pattern.regexp.pattern)
print(f"# pycalver pattern: '{raw_pattern}'")
print("# " + regexfmt.regex101_url(pattern.regexp.pattern)) print("# " + regexfmt.regex101_url(pattern.regexp.pattern))
print(pyexpr_regex) print(pyexpr_regex)
print() print()
@ -258,12 +258,19 @@ def _grep(
count=True, count=True,
help="Control log level. -vv for debug level.", help="Control log level. -vv for debug level.",
) )
@click.option(
"--version-pattern",
default=None,
metavar="<PATTERN>",
help="Pattern to use for placeholders: {version}/{pep440_version}",
)
@click.argument("pattern") @click.argument("pattern")
@click.argument('files', nargs=-1, type=click.File('r')) @click.argument('files', nargs=-1, type=click.File('r'))
def grep( def grep(
pattern: str, pattern : str,
files : typ.Tuple[io.TextIOWrapper], files : typ.Tuple[io.TextIOWrapper],
verbose: int = 0, version_pattern: typ.Optional[str] = None,
verbose : int = 0,
) -> None: ) -> None:
"""Search file(s) for a version pattern.""" """Search file(s) for a version pattern."""
verbose = max(_VERBOSE, verbose) verbose = max(_VERBOSE, verbose)
@ -271,16 +278,29 @@ def grep(
raw_pattern = pattern # use internal naming convention raw_pattern = pattern # use internal naming convention
is_version_pattern_required = "{version}" in raw_pattern or "{pep440_version}" in raw_pattern
if is_version_pattern_required and version_pattern is None:
logger.error(
"Argument --version-pattern=<PATTERN> is required"
" for placeholders: {version}/{pep440_version}."
)
sys.exit(1)
elif is_version_pattern_required:
normalize_pattern = v2patterns.normalize_pattern(version_pattern, raw_pattern)
else:
normalize_pattern = raw_pattern
isatty = getattr(sys.stdout, 'isatty', lambda: False) isatty = getattr(sys.stdout, 'isatty', lambda: False)
if isatty(): if isatty():
colorama.init() colorama.init()
try: try:
_grep(raw_pattern, files, color=True) _grep(normalize_pattern, files, color=True)
finally: finally:
colorama.deinit() colorama.deinit()
else: else:
_grep(raw_pattern, files, color=False) _grep(normalize_pattern, files, color=False)
@cli.command() @cli.command()
@ -448,7 +468,7 @@ def init(verbose: int = 0, dry: bool = False) -> None:
"""Initialize [pycalver] configuration.""" """Initialize [pycalver] configuration."""
_configure_logging(verbose=max(_VERBOSE, verbose)) _configure_logging(verbose=max(_VERBOSE, verbose))
ctx, cfg = config.init(project_path=".") ctx, cfg = config.init(project_path=".", cfg_missing_ok=True)
if cfg: if cfg:
logger.error(f"Configuration already initialized in {ctx.config_rel_path}") logger.error(f"Configuration already initialized in {ctx.config_rel_path}")
@ -496,7 +516,7 @@ def _update_cfg_from_vcs(cfg: config.Config, fetch: bool) -> config.Config:
@click.option( @click.option(
"--release", "--release",
default=None, default=None,
metavar="<name>", metavar="<NAME>",
help=( help=(
f"Override release name of current_version. Valid options are: " f"Override release name of current_version. Valid options are: "
f"{', '.join(VALID_RELEASE_TAG_VALUES)}." f"{', '.join(VALID_RELEASE_TAG_VALUES)}."
@ -520,7 +540,7 @@ def _update_cfg_from_vcs(cfg: config.Config, fetch: bool) -> config.Config:
@click.option( @click.option(
"--date", "--date",
default=None, default=None,
metavar="<iso-date>", metavar="<ISODATE>",
help=f"Set explicit date in format YYYY-0M-0D (e.g. {_current_date}).", help=f"Set explicit date in format YYYY-0M-0D (e.g. {_current_date}).",
) )
def bump( def bump(

View file

@ -401,7 +401,7 @@ def _parse_raw_config(ctx: ProjectContext) -> RawConfig:
return raw_cfg return raw_cfg
def parse(ctx: ProjectContext) -> MaybeConfig: def parse(ctx: ProjectContext, cfg_missing_ok: bool = False) -> MaybeConfig:
"""Parse config file if available.""" """Parse config file if available."""
if ctx.config_filepath.exists(): if ctx.config_filepath.exists():
try: try:
@ -411,15 +411,17 @@ def parse(ctx: ProjectContext) -> MaybeConfig:
logger.warning(f"Couldn't parse {ctx.config_rel_path}: {str(ex)}") logger.warning(f"Couldn't parse {ctx.config_rel_path}: {str(ex)}")
return None return None
else: else:
logger.warning(f"File not found: {ctx.config_rel_path}") if not cfg_missing_ok:
logger.warning(f"File not found: {ctx.config_rel_path}")
return None return None
def init( def init(
project_path: typ.Union[str, pl.Path, None] = "." project_path: typ.Union[str, pl.Path, None] = ".",
cfg_missing_ok: bool = False,
) -> typ.Tuple[ProjectContext, MaybeConfig]: ) -> typ.Tuple[ProjectContext, MaybeConfig]:
ctx = init_project_ctx(project_path) ctx = init_project_ctx(project_path)
cfg = parse(ctx) cfg = parse(ctx, cfg_missing_ok)
return (ctx, cfg) return (ctx, cfg)