diff --git a/osc/commands_git/pr_get.py b/osc/commands_git/pr_get.py index 605db13c..c4505974 100644 --- a/osc/commands_git/pr_get.py +++ b/osc/commands_git/pr_get.py @@ -53,6 +53,9 @@ class PullRequestGetCommand(osc.commandline_git.GitObsCommand): print(tty.colorize("Timeline:", "bold")) timeline = gitea_api.IssueTimelineEntry.list(self.gitea_conn, owner, repo, pull) for entry in timeline: + if entry._data is None: + print(f"{tty.colorize('ERROR', 'red,bold,blink')}: Gitea returned ``None`` instead of a timeline entry") + continue text, body = entry.format() if text is None: continue diff --git a/osc/commands_git/pr_review_interactive.py b/osc/commands_git/pr_review_interactive.py index 9d359b8c..926e45b5 100644 --- a/osc/commands_git/pr_review_interactive.py +++ b/osc/commands_git/pr_review_interactive.py @@ -228,6 +228,9 @@ class PullRequestReviewInteractiveCommand(osc.commandline_git.GitObsCommand): timeline_lines = [] timeline_lines.append(tty.colorize("Timeline:", "bold")) for entry in timeline: + if entry._data is None: + timeline_lines.append(f"{tty.colorize('ERROR', 'red,bold,blink')}: Gitea returned ``None`` instead of a timeline entry") + continue text, body = entry.format() if text is None: continue diff --git a/osc/gitea_api/common.py b/osc/gitea_api/common.py index a6a9779b..26b6ff4b 100644 --- a/osc/gitea_api/common.py +++ b/osc/gitea_api/common.py @@ -12,7 +12,18 @@ from .connection import GiteaHTTPResponse class GiteaModel: - def __init__(self, data, *, response: Optional[GiteaHTTPResponse] = None, conn: Optional[Connection] = None): + def __init__( + self, + data, + *, + check_data: bool = True, + response: Optional[GiteaHTTPResponse] = None, + conn: Optional[Connection] = None, + ): + if check_data and not isinstance(data, dict): + # Gitea sometimes fails to serialize an object and returns ``None`` instead + raise ValueError(f"Unable to instantiate model {self.__class__.__name__} from the following data: {data}") + self._data = data self._response = response self._conn = conn diff --git a/osc/gitea_api/issue_timeline_entry.py b/osc/gitea_api/issue_timeline_entry.py index b39d4067..02b8a90f 100644 --- a/osc/gitea_api/issue_timeline_entry.py +++ b/osc/gitea_api/issue_timeline_entry.py @@ -235,6 +235,7 @@ class IssueTimelineEntry(GiteaModel): ) -> List["IssueTimelineEntry"]: """ List issue timeline entries (applicable to issues and pull request). + HACK: the resulting list may contain instances wrapping ``None`` instead of dictionary with data! :param conn: Gitea ``Connection`` instance. :param owner: Owner of the repo. @@ -246,5 +247,5 @@ class IssueTimelineEntry(GiteaModel): } url = conn.makeurl("repos", owner, repo, "issues", str(number), "timeline", query=q) response = conn.request("GET", url) - obj_list = [cls(i, response=response, conn=conn) for i in response.json() or []] + obj_list = [cls(i, response=response, conn=conn, check_data=False) for i in response.json() or []] return obj_list