Skip to content

Commit

Permalink
Fixed queries after github enablement (#24)
Browse files Browse the repository at this point in the history
Makes incoming query work on both supported backends.
  • Loading branch information
ssbarnea authored Sep 29, 2020
1 parent 02c999e commit 0fa0063
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 37 deletions.
32 changes: 15 additions & 17 deletions lib/gri/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from rich.markdown import Markdown
from rich.table import Table

from gri.abc import Server
from gri.abc import Query, Server
from gri.console import TERMINAL_THEME, bootstrap, get_logging_level
from gri.constants import RC_CONFIG_ERROR, RC_PARTIAL_RUN
from gri.gerrit import GerritServer
Expand Down Expand Up @@ -66,6 +66,7 @@ def __init__(self, ctx: click.Context) -> None:
self.servers: List[Server] = []
self.user = ctx.params["user"]
self.errors = 0 # number of errors encountered
self.query_details: List[str] = []
server = ctx.params["server"]
try:
for srv in (
Expand Down Expand Up @@ -96,10 +97,11 @@ def __init__(self, ctx: click.Context) -> None:
self.reviews: List[Review] = list()
term.print(self.header())

def run_query(self, query: str) -> int:
def run_query(self, query: Query) -> int:
"""Performs a query and stores result inside reviews attribute"""
errors = 0
self.reviews.clear()
self.query_details = []
for item in self.servers:

try:
Expand All @@ -108,6 +110,8 @@ def run_query(self, query: str) -> int:
except (HTTPError, RuntimeError) as exc:
LOG.error(exc)
errors += 1
self.query_details.append(item.mk_query(query))

return errors

def header(self) -> str:
Expand All @@ -116,7 +120,7 @@ def header(self) -> str:

def report(
self,
query: str = None,
query: Query,
title: str = "Reviews",
max_score: int = 1,
action: Optional[str] = None,
Expand Down Expand Up @@ -154,8 +158,7 @@ def report(
term.print()
term.print(table)

extra = f" from: [cyan]{query}[/]" if query else ""
term.print(f"[dim]-- {cnt} changes listed{extra}[/]")
term.print(f"[dim]-- {cnt} changes listed {self.query_details}[/]")

def display_config(self) -> None:
msg = yaml.dump(
Expand Down Expand Up @@ -269,19 +272,18 @@ def owned(ctx):
"""Changes originated from current user (implicit)"""
# query = "status:open"
# query += f" owner:{ctx.obj.user}"
query = "owned"
if ctx.obj.user == "self":
title = "Own reviews"
else:
title = f"Reviews owned by {ctx.obj.user}"
ctx.obj.report(query=query, title=title)
ctx.obj.report(query=Query("owned"), title=title)


@cli.command()
@click.pass_context
def incoming(ctx):
"""Incoming reviews"""
ctx.obj.report(query="incoming", title=incoming.__doc__)
ctx.obj.report(query=Query("incoming"), title=incoming.__doc__)


@cli.command()
Expand All @@ -293,8 +295,7 @@ def incoming(ctx):
)
def merged(ctx, age):
"""Merged in the last number of days"""
query = f"status:merged -age:{age}d owner:{ctx.obj.user}"
ctx.obj.report(query=query, title=f"Merged Reviews ({age}d)")
ctx.obj.report(query=Query("merged", age=age), title=f"Merged Reviews ({age}d)")


# @cli.command()
Expand All @@ -309,16 +310,14 @@ def merged(ctx, age):
@click.pass_context
def watched(ctx):
"""Watched reviews based on server side filters"""
query = f"watchedby:{ctx.obj.user} status:open"
ctx.obj.report(query=query, title=watched.__doc__)
ctx.obj.report(query=Query("watched"), title=watched.__doc__)


@cli.command()
@click.pass_context
def draft(ctx):
"""Draft reviews or with draft comments."""
query = "status:open owner:self has:draft OR draftby:self"
ctx.obj.report(query=query, title=draft.__doc__)
ctx.obj.report(query=Query("draft"), title=draft.__doc__)


@cli.command()
Expand All @@ -332,12 +331,11 @@ def draft(ctx):
def abandon(ctx, age):
"""Abandon changes (delete for drafts) when they are >90 days old
and with very low score. Requires -f to perform the action."""
query = f"status:open age:{age}d owner:{ctx.obj.user}"

ctx.obj.report(
query=query,
query=Query("abandon", age=age),
title=f"Reviews to abandon ({age}d)",
max_score=0.1,
max_score=1.0,
action="abandon",
)

Expand Down
11 changes: 9 additions & 2 deletions lib/gri/abc.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
import datetime
from abc import ABC
from dataclasses import dataclass
from typing import Dict, List

from gri.console import link
from gri.label import Label


@dataclass
class Query:
name: str
age: int = 0


class Server(ABC): # pylint: disable=too-few-public-methods
def __init__(self) -> None:
self.name = "Unknown"

def query(self, query=None) -> List:
def query(self, query: Query) -> List:
raise NotImplementedError()

def mk_query(self, query: str) -> str:
def mk_query(self, query: Query) -> str:
raise NotImplementedError()


Expand Down
24 changes: 17 additions & 7 deletions lib/gri/gerrit.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import requests
from requests.auth import HTTPBasicAuth, HTTPDigestAuth

from gri.abc import Server
from gri.abc import Query, Server
from gri.review import ChangeRequest

try:
Expand Down Expand Up @@ -73,7 +73,7 @@ def __init__(self, url: str, name: str = "", ctx=None) -> None:
}
)

def query(self, query=None) -> List:
def query(self, query: Query) -> List:

gerrit_query = self.mk_query(query)

Expand All @@ -90,13 +90,23 @@ def query(self, query=None) -> List:
for r in self.parsed(self.__session.get(url))
]

def mk_query(self, query: str) -> str:
if query == "owned":
def mk_query(self, query: Query) -> str:
if query.name == "owned":
return f"status:open owner:{self.ctx.obj.user}"
if query == "incoming":
if query.name == "incoming":
return f"reviewer:{self.ctx.obj.user} status:open"

raise NotImplementedError(f"{query} query not implemented by {self.__class__}")
if query.name == "watched":
return f"watchedby:{self.ctx.obj.user} status:open"
if query.name == "abandon":
return f"status:open age:{query.age}d owner:{self.ctx.obj.user}"
if query.name == "draft":
return "status:open owner:self has:draft OR draftby:self"
if query.name == "merged":
return f"status:merged -age:{query.age}d owner:{self.ctx.obj.user}"

raise NotImplementedError(
f"{query.name} query not implemented by {self.__class__}"
)

@staticmethod
def parsed(result) -> dict:
Expand Down
32 changes: 21 additions & 11 deletions lib/gri/github.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import datetime
import logging
import os
from datetime import datetime, timedelta
from typing import Dict, List

import github

from gri.abc import Review, Server
from gri.abc import Query, Review, Server
from gri.review import Label

try:
Expand All @@ -25,9 +25,9 @@ def __init__(self, url: str, name: str = "", ctx=None) -> None:
token = os.environ.get("HOMEBREW_GITHUB_API_TOKEN")
self.github = github.Github(login_or_token=token)

def query(self, query=None) -> List:
def query(self, query: Query) -> List:
reviews = []
limit = 5
limit = 10
results = self.github.search_issues(self.mk_query(query))
for _, item in zip(range(limit), results):
review = PullRequest(data=item.raw_data, server=self)
Expand All @@ -36,13 +36,25 @@ def query(self, query=None) -> List:
# print(mine)
return reviews

def mk_query(self, query: str) -> str: # pylint: disable=no-self-use
def mk_query(self, query: Query) -> str: # pylint: disable=no-self-use
"""Return query string based on """
if query == "owned":
# https://docs.github.com/en/free-pro-team@latest/github/searching-for-information-on-github/searching-issues-and-pull-requests
if query.name == "owned":
return "is:pr is:open author:@me"
if query == "incoming":
if query.name == "incoming":
return "is:pr is:open involves:@me -author:@me"
raise NotImplementedError(f"Unable to build query for {query}")
if query.name == "watched":
return "is:pr is:open involves:@me -author:@me"
if query.name == "abandon":
day = (datetime.now() - timedelta(days=query.age)).date().isoformat()
return f"is:pr is:open author:@me updated:<={day}"
if query.name == "draft":
return "is:pr draft:true is:open author:@me"
if query.name == "merged":
day = (datetime.now() - timedelta(days=query.age)).date().isoformat()
return f"is:pr is:merged author:@me updated:>={day}"

raise NotImplementedError(f"Unable to build query for {query.name}")


class PullRequest(Review): # pylint: disable=too-many-instance-attributes
Expand All @@ -54,9 +66,7 @@ def __init__(self, data: dict, server) -> None:
self.data = data
# LOG.error(data)
self.server = server
self.updated = datetime.datetime.strptime(
self.data["updated_at"], "%Y-%m-%dT%H:%M:%SZ"
)
self.updated = datetime.strptime(self.data["updated_at"], "%Y-%m-%dT%H:%M:%SZ")
self.state = data["state"]
path = urlparse(self.url).path.split("/")
self.org = path[1]
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ setup_requires =
install_requires =
click>=7.1.2
click-help-colors>=0.6
dataclasses; python_version<"3.7"
pygithub
pyyaml>=5.3.1
requests
Expand Down

0 comments on commit 0fa0063

Please sign in to comment.