def get_time(days_bfield, start_time, stop_time):
	id_tuple = (days_bfield, start_time, stop_time)
	
	if start_time == 'WEB':
		if get_time.web_time is not None: return get_time.web_time

		try:
			time = time.sess.query(TimePref).filter_by(time_type='online').one()
		except NoResultFound:
			time = TimePref(time_type='online')
			#sess.add(time)
		get_time.web_time = time
		return time

	if id_tuple in get_time.times:
		time = get_time.times[id_tuple]
		app.logger.debug('found time %r in the cache' % time)
		return time


	days_dict = bfield2dict(days_bfield)
	start_time = timestr2time(str(start_time))
	stop_time = timestr2time(str(stop_time))

	try:
		time = sess.query(TimePref).filter_by(
			time_type='normal',
			start_time=start_time,
			stop_time=stop_time,
			Sa=False, Su=False,
			**days_dict
		).one()

		get_time.times[id_tuple] = time
		app.logger.debug('found time %r in the db' % time)
		return time
	except NoResultFound:
		time = TimePref()
		time.start_time = start_time
		time.stop_time = stop_time
		time.update(Sa=False,Su=False,**days_dict)

		#sess.add(time)
		app.logger.debug('Adding time %r to the db' % time)
		#sess.commit()

		get_time.times[id_tuple] = time
		return time
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')