def upload_courses_flat(): """Upload "flat" courses file, one row per course""" require_auth('admin') if request.method == 'POST': reset_memo_cache() clear_course_pref_data() errors = [] reader = csv.DictReader(request.files['courses_file']) for row in reader: course = Course() course.crn = row['CRN'] if not course.crn: errors.append('Course missing a CRN, row=%r' % row) ## Theme ## theme_name = row['Theme'] #clean theme name, for example turn "GLOBAL PERSPECTIVES: EUROPE" into simply "GLOBAL PERSPECTIVES" if ': ' in theme_name: theme_name = theme_name.rsplit(': ')[0] theme_name = theme_name.strip() if not theme_name: errors.append('Theme name missing for course with CRN %s' % course.crn) else: course.prefs.append( get_pref('Theme', theme_name) ) ## Faculty ## faculty_name = '' last_name = row['Faculty Last Name'].strip() first_name = row['Faculty First Name'].strip() if first_name and last_name: faculty_name = last_name + ', ' + first_name elif last_name or first_name: faculty_name = last_name or first_name if faculty_name: course.prefs.append( get_pref('Faculty', faculty_name) ) else: errors.append('Both first and last faculty name for course with CRN %s is empty' % course.crn) ## Time ## time = TimePref() time_name = row['Corresponding Time'] if time.parse_name(time_name): time = get_time_by_obj(time) course.time = time course.prefs.append(course.time) else: errors.append('Time with name %s not parseable, must be in format, MTWRF 000-2459 with optional trailing' % time_name) if 'Assigned Mentor' in row and row['Assigned Mentor'].strip(): course.pre_assn_mentor_odin = row['Assigned Mentor'].strip() sess.add(course) #all missing errors app.logger.debug('Course Upload Errors: %r' % errors) sess.commit() return redirect(url_for('list_courses')) else: return render_response('upload_courses_flat.html')
def upload_courses(): """Upload Courses from banweb dump, "folding" mentored inquiries for each course into the course""" require_auth('admin') if request.method == 'POST': reset_memo_cache() reader = csv.DictReader(request.files['courses_file']) courses = {} #row of tuples, first value contains a master row #second value contains list of Mentored Inqueries clear_course_pref_data() #1st pass group MENTORED INQUIRY with main course for row in reader: if 'MENTORED INQUIRY' in row['CATALOG TITLE'] or 'MENT INQ' in row['CATALOG TITLE']: #attach mentored inquiry to assoc. course course_no = row['COURSE NO'] #decrease ascii value of final character by one #to turn for example 101B into 101A rel_course = course_no[0:-1] + chr(ord(course_no[-1]) - 1) if rel_course not in courses: #Courses may be out of order, so 101B might come before 101A courses[rel_course] = (None, [row]) else: courses[rel_course][1].append(row) else: courses[row['COURSE NO']] = (row, []) #2nd pass turn the grouped courses into a single SQLAlchemy object for master_course, inquiries in courses.values(): course = Course() course.crn = master_course['CRN'] course.prefs = [] #handle faculty pref faculty_name = master_course['INSTR LAST NAME'] + ', ' + master_course['INSTR FIRST NAME'] faculty_pref = get_pref('Faculty', faculty_name) course.prefs.append(faculty_pref) #theme pref theme_pref = get_pref('Theme', master_course['CATALOG TITLE']) course.prefs.append(theme_pref) #time pref all_courses = inquiries + [ master_course ] days_bfield = reduce(operator.or_, map(course2bfield, all_courses)) start_time = min([int(c['BEGIN TIME']) for c in all_courses]) stop_time = max([int(c[ 'END TIME']) for c in all_courses]) course.time = get_time(days_bfield,start_time,stop_time) course.prefs.append(course.time) sess.add(course) sess.commit() return redirect(url_for('list_courses')) else: #display form return render_response('upload_courses.html')