Commit ee4b01f7 authored by Cyril Matthey-Doret's avatar Cyril Matthey-Doret
Browse files

allow send_feedback script to fill fields in template from arbitrary

feedback columns
parent afe4a61a
Pipeline #329359 passed with stage
in 10 seconds
......@@ -9,6 +9,8 @@
import sys
import json
from string import Formatter
from typing import Dict
import requests
import click
import pandas as pd
......@@ -18,6 +20,9 @@ from teach_utils.common_requests import parse_repo_url
FEEDBACK_TEMPLATE = """
# {project}, group {group}
## Members:
{members}
Please find below your grade and specific comments for this project:
## Grade:
......@@ -28,8 +33,32 @@ Please find below your grade and specific comments for this project:
"""
def fill_template(content: Dict[str, str], template: str) -> str:
"""Replace fields surrounded by {} in template by the value
of corresponding keys in content.
Examples
--------
>>> content = {'name': 'Bob'}
>>> fill_template(content, 'I am {name}')
'I am Bob'
>>> fill_template(content | {'age': 3}, 'I am {age} yo')
'I am 3 yo'
>>> fill_template(content, 'I am {age} yo.') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
ValueError: Fields missing from content: ['age']
"""
try:
# Replace content in issue template
return template.format(**content)
except KeyError:
templ_flds = [fld for _, fld, _, _ in Formatter().parse(template) if fld]
missing_flds = [fld for fld in templ_flds if fld not in content.keys()]
raise ValueError(f"Fields missing from content: {missing_flds}") from None
@click.command()
@click.argument("feedback", type=click.Path(exists=True))
@click.argument("forks", type=click.File(mode="r"), default=sys.stdin)
@click.option(
"--token",
......@@ -39,14 +68,21 @@ Please find below your grade and specific comments for this project:
@click.option(
"--template",
type=click.Path(exists=True),
help="Markdown template for the issue. If present, fields {group}, {project}, {grade} and {comments} will "
"be replaced by their values using the feedback file.",
help="Markdown template for the issue. Fields surrounded by {} in the template will be replaced "
"by content from corresponding columns in feedback.csv. By default, a template with fields {project}, "
"{group}, {members}, {grade} and {comments} is used.",
default=None,
)
@click.option(
"--feedback",
type=click.Path(exists=True),
help="CSV file with column 'id', and additional columns matchine fields in the template"
"The id column should match a gitlab project ID from the JSON input.",
default=None,
)
def main(forks, feedback, token, template):
"""
Send feedback to repositories in input JSON by opening issues.
The feedback table should be a CSV file with columns "id", "grade" and "comments".
The id column should match a gitlab project ID from the JSON input
"""
# Build header with authentication token
......@@ -57,7 +93,6 @@ def main(forks, feedback, token, template):
header = {"PRIVATE-TOKEN": token}
forks = json.load(forks)
feedback = pd.read_csv(feedback)
# Load issue template if provided
if template:
......@@ -65,15 +100,25 @@ def main(forks, feedback, token, template):
else:
feedback_template = FEEDBACK_TEMPLATE
for fork in forks:
# Replace content for current project in issue template
base, group, repo = parse_repo_url(fork["url"])
grade, comments = feedback.loc[
feedback["id"] == fork["id"], ["grade", "comments"]
].values[0]
description = feedback_template.format(
project=repo, group=group, grade=grade, comments=comments
)
# Get basic fields from repo metadata in json
base, group, repo = parse_repo_url(fork["url"])
members = "\n".join([f"* {member['name']}" for member in fork["members"]])
fill_data = {"project": repo, "group": group, "members": members}
# If provided, get additional fields from feedback table
if feedback:
feedback_fields = (
pd.read_csv(feedback)
.query(f'id == {fork["id"]}')
.iloc[0]
.drop("id")
.to_dict()
)
fill_data |= feedback_fields
# Replace fields in the template by their value for the current fork
description = fill_template(fill_data, feedback_template)
# Create issue
requests.post(
f"{base}/api/v4/projects/{fork['id']}/issues?confidential=true&title=Feedback",
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment