diff --git a/scripts/validate_groups b/scripts/validate_groups index c28cb90..65990a0 100755 --- a/scripts/validate_groups +++ b/scripts/validate_groups @@ -1,269 +1,269 @@ #!/usr/bin/env python3 import os import subprocess import mailer import argparse import getpass import random import Slides.class_helper as ch config = ch.get_class_config() parser = argparse.ArgumentParser( description='Validate groups for homeworks') parser.add_argument('-n', '--homework', type=str, help='specify the homework label', required=True) parser.add_argument('-t', '--target', type=str, help='Specify the name of a mail box' ' to send test messages,' 'default : guillaume.anciaux@epfl.ch', default=config['teachers'][0]) parser.add_argument('-u', '--username', type=str, help='Username to log to the SMTP server', default=None) args = parser.parse_args() students_list = config['students'] homework = config['homeworks'][args.homework] group_list = homework['groups'] group_list.rename(columns={"Student #1 EPFL email": "email1", - "Student #2 EPFL email": "email2"}, + "Student #2 EPFL email": "email2", + "Homeworks repository": "repository" + }, inplace=True) group_list = group_list.applymap( lambda x: x.strip() if isinstance(x, str) else x) target = args.target username = args.username password = None if username: print('login:', username) password = getpass.getpass() # ############################################################### # generate group keys students_registered_in_group = list() def make_group_keys(group): emails = [group.email1, group.email2] emails.sort() if len(emails) < 2: raise RuntimeError( 'invalid group: ' + str(emails)) print(emails) key = '_'.join(emails) students_registered_in_group.extend(emails) return key group_keys = group_list.apply(make_group_keys, axis=1) group_list['group_key'] = group_keys group_list.set_index('group_key', inplace=True) students_registered_in_group = set(students_registered_in_group) # ############################################################### # prepare to clone try: os.mkdir('homeworks') except Exception: pass # ############################################################### -def run_command(cmd, on_failure=None, on_success=None): +def run_command(cmd): process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output = process.communicate() output = [i.decode().strip() for i in output if i.decode().strip() != ''] output = '\n'.join(output) ret = process.returncode - if ret != 0: - print('Failed: group ' + key) - print(cmd) - print(output) - if on_failure is not None: - on_failure() - else: - if on_success is not None: - on_success() return ret # ############################################################### # search for failing to clone groups -groups_failing_to_clone = set() - -for key, group in group_list.iterrows(): +def clone_group_repo(group): dirname = os.path.join( - 'homeworks', args.homework, key) + 'homeworks', args.homework, group.name) if os.path.isdir(dirname): - print('Success: group ' + key) - continue - cmd = group['Homeworks repository'] + ' ' + dirname - ret = run_command(cmd, - on_failure=lambda: groups_failing_to_clone.add(key), - on_success=lambda: print('Success: group ' + key) - ) + ret = 0 + else: + clone_cmd = group.repository + ' ' + dirname + ret = run_command(clone_cmd) if ret == 0: - continue + print('Success: group ' + group.name) + + return ret == 0 - group_emails = [group.email1, group.email2] - repo = group[5] + +clone_success = group_list.apply(clone_group_repo, axis=1) +group_list['clone_success'] = clone_success + +# send emails o failed clones + + +def send_failed_clone_email(group): + print('AAAA', group.repository) if username: mailer.mail( username=username, password=password, sender_email=target, subject='SP4E homeworks: error in cloning your project', copy_mail=config['teachers']+config['assistants'], message=f""" Dear Students, Apparently we cannot clone your repository: -{repo} +{group.repository} Please fix the permissions. Best regards, The teaching team. """, - target_emails=group_emails + target_emails=[group.email1, group.email2] ) + +group_list.query("clone_success==False").apply(send_failed_clone_email, axis=1) + # ############################################################### # search for unregistered students student_list = config["students"] students = set() for k, student in student_list.iterrows(): students.add(student['e-Mail'].strip()) illegally_registered_student = ( students_registered_in_group - students_registered_in_group.intersection(students)) ################################################################ # construct invalid groups invalid_groups = set() for key, group in group_list.iterrows(): group_emails = set([group.email1, group.email2]) if (group.email1 in illegally_registered_student or group.email2 in illegally_registered_student): students_registered_in_group -= group_emails invalid_groups.add(key) else: continue if username: mailer.mail( username=username, password=password, sender_email=target, subject=f'{config["class"]["acronym"]} homeworks: invalid group', message=""" Dear Students, Your group is composed with at least a student not officially registered for the class. Therefore I have to ask you to change the composition of the group. You have to understand that the grading of so many projects is a lot of work. Therefore we will do it only for the registered students. With my best regards, The teaching team. """, copy_mail=config['teachers']+config['assistants'], target_emails=group_emails ) unregistered_list = students - students_registered_in_group ################################################################ # send email to unregistered people unregistered_list = list(unregistered_list) random.shuffle(unregistered_list) if len(unregistered_list): if len(unregistered_list) % 2 == 0: random_groups = [e for e in zip( unregistered_list[::2], unregistered_list[1::2])] else: random_groups = [e for e in zip( unregistered_list[:-1:2], unregistered_list[1:-1:2])] random_groups[-1] = random_groups[-1][0], random_groups[-1][1], unregistered_list[-1] random_groups = [" - {0}".format(", ".join(b)) for b in random_groups] random_groups = '\n'.join(random_groups) if username and len(unregistered_list) > 0: mailer.mail( username=username, password=password, sender_email=target, subject=f'{config["class"]["acronym"]} homeworks: not registered in a group', message=f""" Dear Students, Apparently you did not registered yet to any group. Several reasons might explain this. If it happens that you need to find a pair, please find below the automatically created groups. {random_groups} If the situation does not suit you, please inform us as quickly as possible. You still have to create a repository to store your homework. Please inform us of your repository URI, for instance by filling the [form]({homework["group_form"]}) With my best regards, The teaching team. """, copy_mail=config['teachers']+config['assistants'], target_emails=unregistered_list, markdown=True ) ################################################################ # output info print('total students:', len(students)) print('registered students:', len(students_registered_in_group)) print('unregistered students:', len(unregistered_list)) print('illegally registered students:', len(illegally_registered_student)) print('invalid groups:', len(invalid_groups))