Skip to content

Instantly share code, notes, and snippets.

@stevecassidy
Created October 23, 2019 07:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stevecassidy/03156eb816959c98c3da62890940ed6f to your computer and use it in GitHub Desktop.
Save stevecassidy/03156eb816959c98c3da62890940ed6f to your computer and use it in GitHub Desktop.
Checkout student submissions from Github Classroom
"""Check out student submissions for an assignment"""
# driven by two csv files:
# - export from GitHub Classroom roster containing
# identifier, github_username, github_id, name
# - export from iLearn containing
# 'Email address', 'ID number'
#
# input classroom name and assignment name
# then checks out one repository per student into a directory
# named for the 'ID number'
# reports any missing or extra students
#
import csv
import subprocess
import os
def read_github_roster(csvfile):
"""Read the roster exported from github, return
a dictionary with email addr as key and github username
as the value"""
result = {}
with open(csvfile) as fd:
reader = csv.DictReader(fd)
for line in reader:
if 'identifier' in line and not line['github_username'] == "":
result[line['identifier']] = line['github_username']
return result
def read_ilearn_export(csvfile):
"""Read the file exported from iLearn, return a
dictionary with email address as the key and
student id as the values"""
result = {}
with open(csvfile) as fd:
reader = csv.DictReader(fd)
for line in reader:
if 'Email address' in line:
result[line['Email address']] = line['ID number']
return result
def merge_students(github, ilearn):
"""Generate one dictionary with info from both
rosters, also return a dictionary with people not
in both"""
emails = set(github.keys())
emails = set(emails.union(set(ilearn.keys())))
roster = {}
missing = {}
for email in emails:
if email in github and email in ilearn:
roster[email] = {'github': github[email], 'ilearn': ilearn[email]}
elif email in github:
missing[email] = {'github': github[email]}
else:
missing[email] = {'ilearn': ilearn[email]}
return roster, missing
#
# name=${assignment}-${line}
# git clone ${classroom}${name}
def checkout(config, githubid, studentid):
"""Checkout one student assignment into a directory
named for the student id
"""
if not os.path.exists(config['outdir']):
os.makedirs(config['outdir'])
repo = "%s/%s-%s" % (config['classroom'], config['assignment'], githubid)
cmd = ['git', 'clone', repo, os.path.join(config['outdir'], studentid)]
print(" ".join(cmd))
p1 = subprocess.Popen(cmd, stdout=subprocess.PIPE)
return p1.communicate()
def pull(config, githubid, studentid):
"""make sure we have the latest version of this
repository, checkout if needed or just pull if
we already have a version"""
repodir = os.path.join(config['outdir'], studentid)
if os.path.exists(repodir):
wd = os.getcwd()
try:
os.chdir(repodir)
cmd = ['git', 'pull']
p1 = subprocess.Popen(cmd, stdout=subprocess.PIPE)
finally:
os.chdir(wd)
return p1.communicate()
else:
return checkout(config, githubid, studentid)
if __name__=='__main__':
import sys
github = read_github_roster(sys.argv[1])
ilearn = read_ilearn_export(sys.argv[2])
students, missing = merge_students(github, ilearn)
config = {
'classroom': "git@github.com:MQCOMP257",
'assignment': "data-science-portfolio",
'outdir': 'submissions',
}
for key in students:
checkout(config, students[key]['github'], students[key]['ilearn'])
#pull(config, students[key]['github'], students[key]['ilearn'])
#print("-------MISSING---------")
#for key in missing:
# print(key, missing[key])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment