Select Git revision
preparemoodle.py
-
Christian Rohlfing authoredChristian Rohlfing authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
preparemoodle.py 5.38 KiB
#!/usr/bin/env python
import csv
import os
import shutil # copyfile, make_archive
import argparse, sys
def find_file(pattern, path):
if os.name == "posix":
import subprocess
result = [line[2:] for line in subprocess.check_output(
"find " + path + " -type f -name " + pattern,
shell=True).splitlines()]
result = [tmp.decode("utf-8") for tmp in result]
else:
import fnmatch
result = []
for root, _, files in os.walk(path):
for name in files:
if fnmatch.fnmatch(name, pattern):
result.append(os.path.join(root, name))
return result
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='''
prepares batch upload to Moodle via assignment module.
PDFs in folder 'in' are moved to folder 'tmp' with a certain folder structure and finally zipped to 'out'.
Attention: zip-archive 'out' will be overwritten in the following!
''')
parser.add_argument("-i", "--infolder", default="./pdfs/encrypted",
help="Input folder with PDFs. Default: ./pdfs/encrypted")
parser.add_argument("-c", "--csv", default="./Bewertungen.csv",
help="Moodle grading CSV file, needed to construct the folder names. Default: ./Bewertungen.csv")
parser.add_argument("-o", "--outzip", default="./moodle_feedbacks.zip",
help="Output zip archive. Default: ./moodle_feedbacks.zip")
parser.add_argument("-d", "--dry", action='store_true',
help="Flag for dry run, displays only the folder structure inside the archive moodle_feedbacks.zip")
parser.add_argument("-t", "--tmp", default="./tmp",
help="temporary folder Default: ./tmp")
parser.add_argument("--nowarn", action='store_true',
help="Disables warnings")
args = parser.parse_args()
infolder = args.infolder
csvfilename = args.csv
outzip = args.outzip
tmpfolder = args.tmp
dry = args.dry
nowarn = args.nowarn
numlines = 0
with open(csvfilename, newline='') as csvfile:
numlines = sum(1 for line in csvfile)
print('''Preparing for moodle upload
Processing {} lines
'''.format(numlines))
if dry:
print("Dry run\n")
dryoutput=""
else:
for root, dirs, files in os.walk(tmpfolder):
for f in files:
os.unlink(os.path.join(root, f))
for d in dirs:
shutil.rmtree(os.path.join(root, d))
if os.path.exists(outzip): os.remove(outzip)
with open(csvfilename, newline='') as csvfile:
# Loop over all lines in CSV file
numfoundpdfs = 0
cnt = 0
print("Start iterating...", sep='', end='', flush=True)
reader = csv.reader(csvfile, delimiter=',', quotechar='"')
next(reader) # skip first row in CSV file since this should be the header
for row in reader:
# parse the required fields from the csv file
id = row[0]
id = id.replace("Teilnehmer/in", "")
name = row[1]
matnum = row[2]
# if a pdf file for current student exists, create a directory and copy
# the pdf file to it. The resulting directories can be uploaded to moodle
longpdffile = ''
paths = find_file(matnum + "*.pdf", infolder)
if len(paths) > 0:
longpdffile = paths[0]
if len(paths) > 1: # TODO: implement second loop for enabling distribution of multiple files
raise Exception("More than one PDFs starting with matnum {} found!".format(matnum))
if os.path.isfile(longpdffile):
numfoundpdfs += 1
pdffile = os.path.basename(longpdffile)
folder = "{}_{}_assignsubmission_file_".format(name, id)
longfolder = os.path.join(tmpfolder, folder)
if not dry:
os.mkdir(longfolder)
shutil.copyfile(longpdffile, os.path.join(longfolder, pdffile))
else:
dryoutput += "\n{}".format(os.path.join(folder, pdffile))
else:
if not nowarn:
print("Warning: PDF corresponding to matriculation number {} (id={}, name={}) not available.".format(
matnum, id, name
))
# Progress
if not (cnt % round(numlines/10)):
print(".", sep=' ', end='', flush=True)
cnt += 1
print("done.\n")
print("Found {} PDFs (CSV had {} entries)\n".format(numfoundpdfs, numlines))
print("Searching for matriculation numbers not present in CSV but in PDF input folder:")
# Check for PDFs which are not reflected in CSV (student not registered in Moodle)
numnotfoundmatnums = 0
notfoundmatnums = ""
for root, dirs, files in os.walk(infolder):
for pdffile in files:
if pdffile.endswith(".pdf"):
# Get matriculation number from file
matnum = pdffile[0:6]
# Search in CSV
with open(csvfilename, 'r') as csvfile:
notfound = True
for line in csvfile:
if matnum in line:
notfound = False
if notfound:
numnotfoundmatnums += 1
notfoundmatnums += matnum + ", "
if not nowarn:
print("Warning: Could not find {} in CSV".format(matnum))
if numnotfoundmatnums > 0:
print('''I could not find the following {} matriculation numbers in CSV:
{}'''.format(numnotfoundmatnums, notfoundmatnums))
print("Done.")
# Zipping
if not dry:
print("Zipping")
shutil.make_archive(os.path.splitext(outzip)[0], 'zip', tmpfolder)
else:
print("\nResults from dry ryn:\n{}".format(dryoutput))
print("\nDone.\n")