Source code for ghapi.reviews

# Copyright (C) 2022-2023, François-Guillaume Fernandez.

# This program is licensed under the Apache License 2.0.
# See LICENSE or go to <https://www.apache.org/licenses/LICENSE-2.0> for full license details.

from enum import Enum
from typing import Any, Dict, List, Type, TypeVar, Union

import requests

from .connection import Connection
from .exceptions import verify_status
from .pulls import PullRequest
from .utils import parse_comment, parse_review

__all__ = ["Comment", "Review"]


T = TypeVar("T", bound="Review")


class ReviewAction(str, Enum):
    APPROVE = "APPROVE"
    REQUEST_CHANGES = "REQUEST_CHANGES"
    COMMENT = "COMMENT"


[docs]class Comment: """Implements a comment object Args: path: the relative path to the file that necessitates a comment. body: the text of the review comment. line: the line of the blob in the pull request diff that the comment applies to. For a multi-line comment, the last line of the range that your comment applies to. kwargs: keyword arguments for comment (cf. `Review creation <https://docs.github.com/en/rest/pulls/reviews#create-a-review-for-a-pull-request--parameters>`_) """ def __init__(self, path: str, body: str, line: int, **kwargs: Any) -> None: self.path = path self.body = body self.line = line self.kwargs = kwargs def to_dict(self) -> Dict[str, Any]: """Dumps the comment into a dictionary processable by GitHub API""" return dict(path=self.path, body=self.body, line=self.line, **self.kwargs)
[docs]class Review: r"""Implements a Review object >>> from ghapi import Repository, PullRequest, Review >>> pr = PullRequest(Repository("frgfm", "Holocron"), 260) >>> review = Review(pr, 1212580495) >>> review.get_info() Args: pr: a pull request object review_id: the review identifier conn: connection object """ ROUTES: Dict[str, str] = { "create": "/repos/{owner}/{repo}/pulls/{pull_number}/reviews", "info": "/repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}", "comments": "/repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments", } def __init__(self, pr: PullRequest, review_id: int, conn: Union[Connection, None] = None) -> None: self.pr = pr self.review_id = review_id self.conn = conn if isinstance(conn, Connection) else pr.conn self.reset() def reset(self) -> None: self._info: Union[Dict[str, Any], None] = None self._comments: Union[List[Dict[str, Any]], None] = None @property def info(self) -> Dict[str, Any]: if not isinstance(self._info, dict): self._info = verify_status( requests.get( self.conn.resolve( self.ROUTES["info"].format( owner=self.pr.repo.owner, repo=self.pr.repo.name, pull_number=self.pr.pull_number, review_id=self.review_id, ) ) ), 200, ).json() return self._info
[docs] def get_info(self) -> Dict[str, Any]: """Parses high-level information from the review payload""" return parse_review(self.info)
def _list_comments(self, **kwargs: Any) -> List[Dict[str, Any]]: if not isinstance(self._comments, list): self._comments = verify_status( requests.get( self.conn.resolve( self.ROUTES["comments"].format( owner=self.pr.repo.owner, repo=self.pr.repo.name, pull_number=self.pr.pull_number, review_id=self.review_id, ) ), params=kwargs, ), 200, ).json() return self._comments
[docs] def list_comments(self, **kwargs: Any) -> List[Dict[str, Any]]: """List the comments of a Pull Request Review. Args: kwargs: query parameters of `List review comments <https://docs.github.com/en/rest/pulls/reviews#list-comments-for-a-pull-request-review>`_ Returns: list of comments """ return [parse_comment(comment) for comment in self._list_comments(**kwargs)]
[docs] @classmethod def from_comments( cls: Type[T], pr: PullRequest, body: str, comments: List[Comment], action: ReviewAction = ReviewAction.COMMENT, conn: Union[Connection, None] = None, ) -> T: """Submit a review from comments >>> from ghapi import Repository, PullRequest, Review, Comment >>> pr = PullRequest(Repository("owner-login", "awesome-repo"), 1) >>> pr.conn.set_token("MY_DUMMY_TOKEN") >>> comment = Comment("README.md", "This is weird!", 9) >>> review = Review.from_comments(pr, "Thanks for the PR :pray:", [comment]) Args: pr: a pull request object body: the body text of the pull request review. comments: the review comments action: the review action you want to perform. conn: connection object """ # Create the object review = cls(pr, 1, conn) # Check that the connection is valid (accessing the token property will check that itself) isinstance(review.conn.token, str) # Submit the PR response = verify_status( requests.post( review.conn.resolve( cls.ROUTES["create"].format( owner=pr.repo.owner, repo=pr.repo.name, pull_number=pr.pull_number, ) ), json={ "body": body, "event": action, "comments": [comment.to_dict() for comment in comments], }, headers=review.conn.authorization, ), 200, ).json() # Updated the review id review.review_id = response["id"] # Fill the cache review._info = response return review