Merge branch 'unify-output'
All checks were successful
test / test (push) Successful in 33s
build / build (push) Successful in 2m42s

This commit is contained in:
Torjus Håkestad 2024-10-10 01:00:57 +02:00
commit f81bf8c4df
6 changed files with 61 additions and 30 deletions

View File

@ -1,7 +1,6 @@
import typer import typer
import json import json
from typing import Annotated from typing import Annotated
from rich.console import Console
from nixprstatus.pr import pr_merge_status from nixprstatus.pr import pr_merge_status
from nixprstatus.pr import commits_since from nixprstatus.pr import commits_since
from nixprstatus.watchlist import Watchlist from nixprstatus.watchlist import Watchlist
@ -24,26 +23,17 @@ def pr(
branches: Annotated[ branches: Annotated[
list[str] | None, typer.Option(help="Check specific branch") list[str] | None, typer.Option(help="Check specific branch")
] = None, ] = None,
format: Annotated[
OutputFormat, typer.Option(help="Output format")
] = OutputFormat.CONSOLE,
): ):
"""Get merge status of pull request.""" """Get merge status of pull request."""
console = Console()
if branches: if branches:
status = pr_merge_status(pr, branches) status = pr_merge_status(pr, branches)
else: else:
status = pr_merge_status(pr) status = pr_merge_status(pr)
console.print(f"{status.title}\n", highlight=False) status.print(format=format)
merged = ":white_check_mark: merged" if status.merged else ":x: merged"
console.print(merged, highlight=False)
for branch in status.branches:
output = (
f":white_check_mark: {branch}"
if status.branches[branch]
else f":x: {branch}"
)
console.print(output, highlight=False)
@app.command() @app.command()
@ -69,17 +59,16 @@ def since(
@watchlist_app.command() @watchlist_app.command()
def list(watchlist: str | None = None, format: OutputFormat = OutputFormat.CONSOLE): def list(watchlist: str | None = None, format: OutputFormat = OutputFormat.CONSOLE):
"""List PRs in watchlist.""" """List PRs in watchlist."""
wl = Watchlist.from_file() wl = Watchlist.from_file(path=watchlist)
wl.print(format=format) wl.print(format=format)
@watchlist_app.command() @watchlist_app.command()
def add(pr: int): def add(pr: int, watchlist: str | None = None):
"""Add PR to watchlist.""" """Add PR to watchlist."""
wl = Watchlist.from_file() wl = Watchlist.from_file(path=watchlist)
wl.add_pr(pr) info = wl.add_pr(pr)
wl.to_file() wl.to_file(path=watchlist)
info = wl.pr(pr)
print(f"Added #{info.pr}: {info.title} to watchlist.") print(f"Added #{info.pr}: {info.title} to watchlist.")
@ -87,6 +76,9 @@ def add(pr: int):
def remove(pr: int): def remove(pr: int):
"""Remove PR from watchlist.""" """Remove PR from watchlist."""
wl = Watchlist.from_file() wl = Watchlist.from_file()
if pr not in wl:
print(f"#{pr} not in watchlist.")
return
wl.remove(pr) wl.remove(pr)
wl.to_file() wl.to_file()
print(f"Removed #{pr} from watchlist.") print(f"Removed #{pr} from watchlist.")

6
nixprstatus/output.py Normal file
View File

@ -0,0 +1,6 @@
from enum import Enum
class OutputFormat(str, Enum):
CONSOLE = "console"
JSON = "json"

View File

@ -1,5 +1,8 @@
import requests import requests
from pydantic import BaseModel from pydantic import BaseModel
from rich.console import Console
from nixprstatus.output import OutputFormat
DEFAULT_HEADERS = { DEFAULT_HEADERS = {
"Accept": "application/vnd.github.text+json", "Accept": "application/vnd.github.text+json",
@ -13,6 +16,26 @@ class PRStatus(BaseModel):
merged: bool merged: bool
branches: dict[str, bool] branches: dict[str, bool]
def print(self, format: OutputFormat = OutputFormat.CONSOLE):
match format:
case OutputFormat.JSON:
print(self.model_dump_json())
case OutputFormat.CONSOLE:
console = Console(highlight=False)
console.print(f"{self.title}\n")
merged = ":white_check_mark: merged" if self.merged else ":x: merged"
console.print(merged)
for branch in self.branches:
output = (
f":white_check_mark: {branch}"
if self.branches[branch]
else f":x: {branch}"
)
console.print(output)
case _:
raise ValueError(f"Unknown format: {format}")
def commit_in_branch(commit_sha: str, branch: str) -> bool: def commit_in_branch(commit_sha: str, branch: str) -> bool:
url = f"https://api.github.com/repos/NixOS/nixpkgs/compare/{branch}...{commit_sha}" url = f"https://api.github.com/repos/NixOS/nixpkgs/compare/{branch}...{commit_sha}"

View File

@ -1,16 +1,11 @@
import json import json
import os import os
from enum import Enum
from pathlib import Path from pathlib import Path
from pydantic import BaseModel from pydantic import BaseModel
from rich.console import Console from rich.console import Console
from nixprstatus.pr import get_pr from nixprstatus.pr import get_pr
from nixprstatus.output import OutputFormat
class OutputFormat(str, Enum):
CONSOLE = "console"
JSON = "json"
class PRInfo(BaseModel): class PRInfo(BaseModel):
@ -45,12 +40,14 @@ class Watchlist(BaseModel):
with open(p, "w") as f: with open(p, "w") as f:
f.write(self.model_dump_json()) f.write(self.model_dump_json())
def add_pr(self, pr: int): def add_pr(self, pr: int) -> PRInfo:
# Lookup PR info # Lookup PR info
info = get_pr(pr) info = get_pr(pr)
title = info["title"] title = info["title"]
self.prs.append(PRInfo(pr=pr, title=title)) info = PRInfo(pr=pr, title=title)
self.prs.append(info)
return info
def remove(self, pr: int): def remove(self, pr: int):
self.prs = [p for p in self.prs if p.pr != pr] self.prs = [p for p in self.prs if p.pr != pr]
@ -72,6 +69,13 @@ class Watchlist(BaseModel):
return p return p
return None return None
def __contains__(self, item: PRInfo | int):
match item:
case PRInfo():
return any([x == item for x in self.prs])
case int():
return any([x.pr == item for x in self.prs])
def _default_path() -> str: def _default_path() -> str:
if "XDG_STATE_HOME" in os.environ: if "XDG_STATE_HOME" in os.environ:
@ -79,6 +83,6 @@ def _default_path() -> str:
return "~/.config/nixprstatus/watchlist.json" return "~/.config/nixprstatus/watchlist.json"
def _ensure_default_path() -> str: def _ensure_default_path():
p = Path(_default_path()).expanduser() p = Path(_default_path()).expanduser()
p.parent.mkdir(parents=True, exist_ok=True) p.parent.mkdir(parents=True, exist_ok=True)

View File

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "nixprstatus" name = "nixprstatus"
version = "0.1.4" version = "0.1.5"
description = "Nixpkgs PR status checker" description = "Nixpkgs PR status checker"
authors = ["Torjus Håkestad <torjus@usit.uio.no>"] authors = ["Torjus Håkestad <torjus@usit.uio.no>"]
license = "MIT" license = "MIT"

View File

@ -32,3 +32,9 @@ class TestWatchlist(unittest.TestCase):
w = Watchlist(prs=[PRInfo(pr=1, title="PR 1")]) w = Watchlist(prs=[PRInfo(pr=1, title="PR 1")])
self.assertEqual(w.pr(1), PRInfo(pr=1, title="PR 1")) self.assertEqual(w.pr(1), PRInfo(pr=1, title="PR 1"))
self.assertEqual(w.pr(2), None) self.assertEqual(w.pr(2), None)
def test_contains(self):
w = Watchlist(prs=[PRInfo(pr=1, title="PR 1")])
self.assertIn(PRInfo(pr=1, title="PR 1"), w)
self.assertIn(1, w)
self.assertNotIn(2, w)