Compare commits
	
		
			4 Commits
		
	
	
		
			16-watchli
			...
			unify-outp
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 3064d0231c | |||
| 5c73d55d91 | |||
| 9e70fc25d4 | |||
| 63ee619aef | 
| @@ -25,6 +25,7 @@ Options: | |||||||
|  |  | ||||||
| Commands: | Commands: | ||||||
|   pr         Get merge status of pull request. |   pr         Get merge status of pull request. | ||||||
|   since  Return the count of commits that has happened between the two refs. |   since      Return the count of commits that has happened between the... | ||||||
|  |   watchlist  Manage watchlist. | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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() | ||||||
| @@ -65,29 +55,35 @@ def since( | |||||||
|         return |         return | ||||||
|     typer.echo(count) |     typer.echo(count) | ||||||
|  |  | ||||||
|  |  | ||||||
| @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.") | ||||||
|  |  | ||||||
|  |  | ||||||
| @watchlist_app.command() | @watchlist_app.command() | ||||||
| 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.") | ||||||
|  |  | ||||||
|  |  | ||||||
| def main(): | def main(): | ||||||
|     app() |     app() | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								nixprstatus/output.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								nixprstatus/output.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | from enum import Enum | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class OutputFormat(str, Enum): | ||||||
|  |     CONSOLE = "console" | ||||||
|  |     JSON = "json" | ||||||
| @@ -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}" | ||||||
|   | |||||||
| @@ -1,15 +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): | ||||||
| @@ -44,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] | ||||||
| @@ -71,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: | ||||||
| @@ -78,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) | ||||||
|   | |||||||
| @@ -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" | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user