Skip to content

Commit

Permalink
test: decorate report functions
Browse files Browse the repository at this point in the history
  • Loading branch information
yanksyoon committed Mar 1, 2024
1 parent da385e0 commit bf53ea9
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 13 deletions.
38 changes: 37 additions & 1 deletion repo_policy_compliance/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
"""Individual checks used to compose job checks."""

from enum import Enum
from typing import NamedTuple
from typing import Callable, NamedTuple, ParamSpec, TypeVar

from github import Github
from github.Branch import Branch
from github.Repository import Repository

from repo_policy_compliance import log
from repo_policy_compliance.comment import remove_quote_lines
from repo_policy_compliance.exceptions import GithubClientError
from repo_policy_compliance.github_client import (
get_branch,
get_collaborator_permission,
Expand Down Expand Up @@ -65,6 +66,38 @@ class Report(NamedTuple):

log.setup()

P = ParamSpec("P")
R = TypeVar("R")


def github_exceptions_to_fail_report(func: Callable[P, R]) -> Callable[P, R | Report]:
"""Catch exceptions and convert to failed report with reason.
Args:
func: The function to catch the GithubClient exceptions for.
Returns:
The function where any exceptions raised would be converted to a failed result.
"""

def wrapper(*args: P.args, **kwargs: P.kwargs) -> R | Report:
"""Replace function.
Args:
args: The positional arguments passed to the original method.
kwargs: The keywords arguments passed to the original method.
Returns:
Failed result report if any exceptions were raised. The return value after calling the
wrapped function otherwise.
"""
try:
return func(*args, **kwargs)
except GithubClientError as exc:
return Report(result=Result.FAIL, reason=str(exc))

return wrapper


@log.call
def branch_protected(branch: Branch) -> Report:
Expand All @@ -84,6 +117,7 @@ def branch_protected(branch: Branch) -> Report:
return Report(result=Result.PASS, reason=None)


@github_exceptions_to_fail_report
@inject_github_client
@log.call
def target_branch_protection(
Expand Down Expand Up @@ -133,6 +167,7 @@ def target_branch_protection(
return Report(result=Result.PASS, reason=None)


@github_exceptions_to_fail_report
@inject_github_client
@log.call
def collaborators(github_client: Github, repository_name: str) -> Report:
Expand Down Expand Up @@ -195,6 +230,7 @@ def _branch_external_fork(repository: Repository, source_repository_name: str) -
return True


@github_exceptions_to_fail_report
@inject_github_client
@log.call
def execute_job(
Expand Down
85 changes: 81 additions & 4 deletions src-docs/check.py.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ Individual checks used to compose job checks.

---

<a href="../repo_policy_compliance/check.py#L74"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>
<a href="../repo_policy_compliance/check.py#L73"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>

## <kbd>function</kbd> `exceptions_to_fail_report`
## <kbd>function</kbd> `github_exceptions_to_fail_report`

```python
exceptions_to_fail_report(func: Callable[~P, ~R]) → Callable[~P, ~R]
github_exceptions_to_fail_report(
func: Callable[~P, ~R]
) → Callable[~P, Union[~R, Report]]
```

Catch exceptions and convert to failed report with reason.
Expand All @@ -28,14 +30,89 @@ Catch exceptions and convert to failed report with reason.

**Args:**

- <b>`func`</b>: The function to catch the exceptions for.
- <b>`func`</b>: The function to catch the GithubClient exceptions for.



**Returns:**
The function where any exceptions raised would be converted to a failed result.


---

<a href="../repo_policy_compliance/check.py#L83"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>

## <kbd>function</kbd> `wrapper`

```python
wrapper(*args: args, **kwargs: kwargs) → Union[~R, Report]
```

Replace function.



**Args:**

- <b>`args`</b>: The positional arguments passed to the original method.
- <b>`kwargs`</b>: The keywords arguments passed to the original method.



**Returns:**
Failed result report if any exceptions were raised. The return value after calling the wrapped function otherwise.


---

<a href="../repo_policy_compliance/check.py#L83"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>

## <kbd>function</kbd> `wrapper`

```python
wrapper(*args: args, **kwargs: kwargs) → Union[~R, Report]
```

Replace function.



**Args:**

- <b>`args`</b>: The positional arguments passed to the original method.
- <b>`kwargs`</b>: The keywords arguments passed to the original method.



**Returns:**
Failed result report if any exceptions were raised. The return value after calling the wrapped function otherwise.


---

<a href="../repo_policy_compliance/check.py#L83"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>

## <kbd>function</kbd> `wrapper`

```python
wrapper(*args: args, **kwargs: kwargs) → Union[~R, Report]
```

Replace function.



**Args:**

- <b>`args`</b>: The positional arguments passed to the original method.
- <b>`kwargs`</b>: The keywords arguments passed to the original method.



**Returns:**
Failed result report if any exceptions were raised. The return value after calling the wrapped function otherwise.


---

## <kbd>class</kbd> `Report`
Expand Down
23 changes: 23 additions & 0 deletions tests/unit/test_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,29 @@
from github.Repository import Repository

import repo_policy_compliance
from repo_policy_compliance.check import Result
from repo_policy_compliance.exceptions import GithubClientError


def test_github_exceptions_to_fail_report():
"""
arrange: given a function that raises a GithubClient error.
act: when the function is called with github_exceptions_to_fail_report decorator.
assert: a failed report with exception as reason is returned.
"""

@repo_policy_compliance.check.github_exceptions_to_fail_report
def github_client_error_raiser():
"""A mock function to raise github client error.
Raises:
GithubClientError: always.
"""
raise GithubClientError("Exception message.")

report = github_client_error_raiser()
assert report.result == Result.FAIL
assert report.reason == "Exception message."


@pytest.mark.parametrize(
Expand Down
16 changes: 8 additions & 8 deletions tests/unit/test_github_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from github.Repository import Repository

import repo_policy_compliance.github_client
from repo_policy_compliance.check import target_branch_protection
from repo_policy_compliance.check import Result, target_branch_protection
from repo_policy_compliance.exceptions import GithubClientError

GITHUB_REPOSITORY_NAME = "test/repository"
Expand Down Expand Up @@ -48,12 +48,12 @@ def test_github_error(
repo_policy_compliance.github_client, "get", lambda *_args, **_kwargs: github_client
)

with pytest.raises(GithubClientError) as error:
# The github_client is injected
target_branch_protection( # pylint: disable=no-value-for-parameter
GITHUB_REPOSITORY_NAME, GITHUB_BRANCH_NAME, GITHUB_REPOSITORY_NAME
)
assert expected_message in str(error.value)
# The github_client is injected
report = target_branch_protection( # pylint: disable=no-value-for-parameter
GITHUB_REPOSITORY_NAME, GITHUB_BRANCH_NAME, GITHUB_REPOSITORY_NAME
)
assert report.result == Result.FAIL
assert expected_message in str(report.reason)


def test_get_collaborator_permission_error():
Expand All @@ -67,7 +67,7 @@ def test_get_collaborator_permission_error():

with pytest.raises(GithubClientError) as error:
# The github_client is injected
repo_policy_compliance.github_client.get_collaborator_permission( # pylint: disable=no-value-for-parameter
repo_policy_compliance.github_client.get_collaborator_permission(
mock_repository, "test_user"
)
assert "Invalid collaborator permission" in str(error.value)

0 comments on commit bf53ea9

Please sign in to comment.