Skip to content

Commit a2a4efd

Browse files
committed
[feat] Add --allow-missing option to skip missing issues, fix #4
1 parent 7d5c1af commit a2a4efd

File tree

2 files changed

+50
-7
lines changed

2 files changed

+50
-7
lines changed

repobee_feedback/feedback.py

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,18 @@
2424

2525

2626
def callback(args: argparse.Namespace, api: plug.API) -> None:
27-
repo_names = plug.generate_repo_names(args.students, args.master_repo_names)
27+
repo_names = plug.generate_repo_names(
28+
args.students, args.master_repo_names
29+
)
2830
if "multi_issues_file" in args and args.multi_issues_file is not None:
2931
issues_file = pathlib.Path(args.multi_issues_file).resolve()
3032
all_issues = _parse_multi_issues_file(issues_file)
3133
else:
3234
issues_dir = pathlib.Path(args.issues_dir).resolve()
3335
all_issues = _collect_issues(repo_names, issues_dir)
34-
issues = _extract_expected_issues(all_issues, repo_names)
36+
issues = _extract_expected_issues(
37+
all_issues, repo_names, args.allow_missing
38+
)
3539
for repo_name, issue in issues:
3640
open_issue = args.batch_mode or _ask_for_open(
3741
issue, repo_name, args.truncation_length
@@ -92,6 +96,12 @@ def create_extension_command(self):
9296
"be an #ISSUE# line."
9397
),
9498
)
99+
parser.add_argument(
100+
"--allow-missing",
101+
help="Emit a warning (instead of crashing) on missing issues.",
102+
action="store_true",
103+
default=False,
104+
)
95105
return plug.ExtensionCommand(
96106
parser=parser,
97107
name="issue-feedback",
@@ -121,13 +131,15 @@ def _ask_for_open(issue: plug.Issue, repo_name: str, trunc_len: int) -> bool:
121131
)
122132
)
123133
return (
124-
input('Open issue "{}" in repo {}? (y/n) '.format(issue.title, repo_name))
134+
input(
135+
'Open issue "{}" in repo {}? (y/n) '.format(issue.title, repo_name)
136+
)
125137
== "y"
126138
)
127139

128140

129141
def _extract_expected_issues(
130-
repos_and_issues, repo_names
142+
repos_and_issues, repo_names, allow_missing
131143
) -> List[Tuple[str, plug.Issue]]:
132144
expected_repo_names = set(repo_names)
133145
expected_repos_and_issues = [
@@ -139,7 +151,11 @@ def _extract_expected_issues(
139151
(repo_name for repo_name, _ in expected_repos_and_issues)
140152
)
141153
if missing_repos:
142-
raise plug.PlugError("Missing issues for: " + ", ".join(missing_repos))
154+
msg = "Missing issues for: " + ", ".join(missing_repos)
155+
if allow_missing:
156+
LOGGER.warning(msg)
157+
else:
158+
raise plug.PlugError(msg)
143159

144160
return expected_repos_and_issues
145161

@@ -164,11 +180,15 @@ def _read_issue(issue_path: pathlib.Path) -> plug.Issue:
164180
def _parse_multi_issues_file(
165181
issues_file: pathlib.Path
166182
) -> Iterable[Tuple[str, plug.Issue]]:
167-
with open(str(issues_file), mode="r", encoding=sys.getdefaultencoding()) as file:
183+
with open(
184+
str(issues_file), mode="r", encoding=sys.getdefaultencoding()
185+
) as file:
168186
lines = list(file.readlines())
169187

170188
if not lines or not re.match(BEGIN_ISSUE_PATTERN, lines[0], re.IGNORECASE):
171-
raise plug.PlugError("first line of multi issues file not #ISSUE# line")
189+
raise plug.PlugError(
190+
"first line of multi issues file not #ISSUE# line"
191+
)
172192

173193
issue_blocks = _extract_issue_blocks(lines)
174194
return list(_extract_issues(issue_blocks, lines))

tests/test_feedback.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ def parsed_args_issues_dir(tmp_path):
6161
issues_dir=str(tmp_path),
6262
multi_issues_file=None,
6363
truncation_length=50,
64+
allow_missing=False,
6465
)
6566

6667

@@ -74,6 +75,7 @@ def parsed_args_multi_issues_file(with_multi_issues_file):
7475
issues_dir=None,
7576
multi_issues_file=str(issues_file),
7677
truncation_length=50,
78+
allow_missing=False,
7779
)
7880

7981

@@ -165,6 +167,27 @@ def test_aborts_if_issue_is_missing(
165167
assert repo_without_issue in str(exc_info.value)
166168
assert not api_mock.open_issue.called
167169

170+
def test_ignores_missing_issue_if_allow_missing(
171+
self, with_issues, parsed_args_issues_dir, api_mock, tmp_path
172+
):
173+
"""Test that missing issues are ignored if --allow-mising is set."""
174+
repo_without_issue = plug.generate_repo_name(
175+
STUDENT_TEAM_NAMES[-1], MASTER_REPO_NAMES[0]
176+
)
177+
(tmp_path / "{}.md".format(repo_without_issue)).unlink()
178+
expected_calls = [
179+
mock.call(issue.title, issue.body, [repo_name])
180+
for repo_name, issue in with_issues
181+
if repo_name != repo_without_issue
182+
]
183+
args_dict = vars(parsed_args_issues_dir)
184+
args_dict["allow_missing"] = True
185+
args = argparse.Namespace(**args_dict)
186+
187+
feedback.callback(args=args, api=api_mock)
188+
189+
api_mock.open_issue.assert_has_calls(expected_calls, any_order=True)
190+
168191
def test_opens_nothing_if_open_prompt_returns_false(
169192
self, with_issues, parsed_args_issues_dir, api_mock
170193
):

0 commit comments

Comments
 (0)