cli: add version part filter
continuous-integration/drone/push Build is passing Details

Bug: https://bugs.sysrq.in/show_bug.cgi?id=4
This commit is contained in:
Anna “CyberTailor” 2024-04-23 23:22:22 +05:00
parent d7a99e3903
commit 4935f3fe45
Signed by: CyberTaIlor
GPG Key ID: E7B76EDC50864BB1
6 changed files with 150 additions and 21 deletions

View File

@ -5,9 +5,11 @@
Release Notes
=============
0.6.2
0.7.0
-----
* **New**: Filter oudated packages by version part (:bug:`4`).
*Modules changelog:*
* **pgo**:

View File

@ -68,6 +68,9 @@ class OptionsBase(ABC):
class ModuleOptionsBase(OptionsBase, ABC):
""" Base class for module-specific options. """
#: Extra options used in the command scope.
extra_options: dict[str, Any] | None = None
@property
@abstractmethod
def cache_order(self) -> list[str]:
@ -95,6 +98,15 @@ class BugzillaOptions(ModuleOptionsBase):
return ["chronological_sort", "short_desc", "product", "component"]
@dataclass
class PgoOptions(ModuleOptionsBase):
""" Gentoo Packages subcommand options. """
@cached_property
def cache_order(self) -> list[str]:
return []
@dataclass
class PkgcheckOptions(ModuleOptionsBase):
""" pkgcheck subcommand options. """
@ -155,8 +167,9 @@ class Options(OptionsBase):
# Byte string used for creating cache key.
cache_key: CacheKey = field(default_factory=CacheKey)
# Subcommand options.
#: Subcommand options.
bugzilla: BugzillaOptions = field(default_factory=BugzillaOptions)
pgo: PgoOptions = field(default_factory=PgoOptions)
pkgcheck: PkgcheckOptions = field(default_factory=PkgcheckOptions)
repology: RepologyOptions = field(default_factory=RepologyOptions)

View File

@ -18,7 +18,7 @@ from find_work.cache import (
)
from find_work.cli import Message, Options, ProgressDots
from find_work.constants import PGO_BASE_URL, PGO_API_URL
from find_work.types import VersionBump
from find_work.types import VersionBump, VersionPart
from find_work.utils import aiohttp_session
@ -61,6 +61,9 @@ async def _outdated(options: Options) -> None:
"Filtering by maintainer is not implemented for this command"
)
if (extra_options := options.pgo.extra_options) is not None:
version_part: VersionPart | None = extra_options.get("version_part")
dots = ProgressDots(options.verbose)
options.say(Message.CACHE_LOAD)
@ -78,14 +81,18 @@ async def _outdated(options: Options) -> None:
with dots():
write_json_cache(data, options.cache_key)
outdated_set = _collect_version_bumps(data, options)
for bump in outdated_set:
no_work = True
for bump in _collect_version_bumps(data, options):
if version_part and not bump.changed(version_part):
continue
options.echo(bump.atom + " ", nl=False)
options.secho(bump.old_version, fg="red", nl=False)
options.echo("", nl=False)
options.secho(bump.new_version, fg="green")
no_work = False
if len(outdated_set) == 0:
if no_work:
options.say(Message.NO_WORK)
@ -168,10 +175,18 @@ async def _stabilization(options: Options) -> None:
@click.command()
@click.option("-F", "--filter", "version_part",
type=click.Choice(["major", "minor", "patch"]),
help="Version part filter.")
@click.pass_obj
def outdated(options: Options) -> None:
""" Find outdated packages. """
def outdated(options: Options, version_part: VersionPart | None = None) -> None:
"""
Find outdated packages.
"""
options.cache_key.feed("outdated")
options.pgo.extra_options = {"version_part": version_part}
asyncio.run(_outdated(options))

View File

@ -21,7 +21,7 @@ from find_work.cache import (
write_json_cache,
)
from find_work.cli import Message, Options, ProgressDots
from find_work.types import VersionBump
from find_work.types import VersionBump, VersionPart
from find_work.utils import aiohttp_session
@ -87,6 +87,9 @@ def _collect_version_bumps(data: Iterable[set[Package]],
async def _outdated(options: Options) -> None:
dots = ProgressDots(options.verbose)
if (extra_options := options.repology.extra_options) is not None:
version_part: VersionPart | None = extra_options.get("version_part")
options.say(Message.CACHE_LOAD)
with dots():
cached_data = read_json_cache(options.cache_key)
@ -107,20 +110,32 @@ async def _outdated(options: Options) -> None:
json_data = _projects_to_json(data)
write_json_cache(json_data, options.cache_key)
outdated_set = _collect_version_bumps(data.values(), options)
for bump in outdated_set:
no_work = True
for bump in _collect_version_bumps(data.values(), options):
if version_part and not bump.changed(version_part):
continue
options.echo(bump.atom + " ", nl=False)
options.secho(bump.old_version, fg="red", nl=False)
options.echo("", nl=False)
options.secho(bump.new_version, fg="green")
no_work = False
if len(outdated_set) == 0:
if no_work:
options.say(Message.NO_WORK)
@click.command()
@click.option("-F", "--filter", "version_part",
type=click.Choice(["major", "minor", "patch"]),
help="Version part filter.")
@click.pass_obj
def outdated(options: Options) -> None:
""" Find outdated packages. """
def outdated(options: Options, version_part: VersionPart | None = None) -> None:
"""
Find outdated packages.
"""
options.cache_key.feed("outdated")
options.repology.extra_options = {"version_part": version_part}
asyncio.run(_outdated(options))

View File

@ -3,23 +3,65 @@
# No warranty
"""
Type definitions for the application, implemented (mostly) as Pydantic models.
Type definitions for the application, implemented as enums and Pydantic models.
"""
from dataclasses import field
from enum import Enum, auto
from enum import Enum, StrEnum, auto
from itertools import zip_longest
from pydantic.dataclasses import dataclass
class VersionPart(StrEnum):
MAJOR = auto()
MINOR = auto()
PATCH = auto()
@dataclass(frozen=True, order=True)
class VersionBump:
""" Version bump representation for a Gentoo repository. """
"""
Version bump representation for a Gentoo repository.
"""
atom: str
old_version: str = field(compare=False)
new_version: str = field(compare=False)
def changed(self, stop_after_part: VersionPart) -> bool:
"""
Roughly determine whether versions differ up to the given part.
>>> VersionBump("foo", "1.3.2", "1.4").changed(VersionPart.PATCH)
True
>>> VersionBump("foo", "1.3.2", "2.0").changed(VersionPart.MINOR)
True
>>> VersionBump("foo", "1", "1.0.1").changed(VersionPart.MINOR)
False
>>> VersionBump("foo", "1", "1.1").changed(VersionPart.MINOR)
True
Remember that it doesn't always work correctly:
>>> VersionBump("foo", "1", "1.00").changed(VersionPart.MINOR)
True
"""
def split_version(version: str) -> list[str]:
return version.replace("-", ".").replace("_", ".").split(".")
old_parts = split_version(self.old_version)
new_parts = split_version(self.new_version)
parts = list(zip_longest(old_parts, new_parts, fillvalue="0"))
stop_index = list(VersionPart).index(stop_after_part)
for old, new in parts[:stop_index + 1]:
if old != new:
return True
return False
@dataclass(frozen=True, order=True)
class BugView:

View File

@ -2,7 +2,7 @@
.\" SPDX-FileCopyrightText: 2024 Anna <cyber@sysrq.in>
.\" SPDX-License-Identifier: WTFPL
.\" No warranty
.Dd January 14, 2024
.Dd April 23, 2024
.Dt FIND-WORK 1
.Os
.Sh NAME
@ -17,9 +17,11 @@
.Ar module
.Op Ar arg ...
.Ar command
.Op Ar arg ...
.Sh DESCRIPTION
.Nm
is a fun little tool that lets you discover what you can do for Gentoo as a package mantainer.
is a fun little tool
that lets you discover what you can do for Gentoo as a package mantainer.
It contains filters to show only packages you might be interested in.
.Pp
.Nm
@ -84,8 +86,28 @@ This module uses Gentoo Packages API to find work.
.Ar command
can be one of the following:
.Bl -tag -width Ds
.It Ic outdated Pq alias: Ic out , Ic o
.It Xo
.Ic outdated
.Fl F Ar part
.Xc
.Dl Pq alias: Ic out , Ic o
.Pp
Find outdated packages.
.Pp
This command accepts the following options:
.Bl -tag width Ds
.It Fl F Ar part , Fl -filter Ar part
Least important version part
.Po
major,
minor,
patch
.Pc
change to be displayed.
Version part matching is implemented very roughly
and can lead to false matches.
.El
.
.It Ic stabilization Pq alias: Ic stab , Ic s
Find stabilization candidates.
.El
@ -133,8 +155,28 @@ This module uses Repology API to find work.
.Ar command
can be one of the following:
.Bl -tag -width Ds
.It Ic outdated Pq alias: Ic out , Ic o
.It Xo
.Ic outdated
.Fl F Ar part
.Xc
.Dl Pq alias: Ic out , Ic o
.Pp
Find outdated packages.
.Pp
This command accepts the following options:
.Bl -tag width Ds
.It Fl F Ar part , Fl -filter Ar part
Least important version part
.Po
major,
minor,
patch
.Pc
change to be displayed.
Version part matching is implemented very roughly
and can lead to false matches.
.El
.
.El
.Pp
The options for