Example #1
0
def get_or_create_semester(strm):
    if not (isinstance(strm, basestring) and strm.isdigit() and len(strm)==4):
        raise ValueError, "Bad strm: " + repr(strm)
    oldsem = Semester.objects.filter(name=strm)
    if oldsem:
        return oldsem[0]

    db = SIMSConn()
    db.execute("SELECT strm, term_begin_dt, term_end_dt FROM ps_term_tbl WHERE strm=%s", (strm,))
    row = db.fetchone()
    if row is None:
        raise ValueError, "Not Found: %r" % (strm)
    strm, st, en = row
    
    # create Semester object
    st = datetime.datetime.strptime(st, "%Y-%m-%d").date()
    en = datetime.datetime.strptime(en, "%Y-%m-%d").date()
    sem = Semester(name=strm, start=st, end=en)
    sem.save()
    
    # also create SemesterWeek object for the first week
    first_monday = st
    while first_monday.weekday() != 0:
        first_monday += datetime.timedelta(days=1)    
    wk = SemesterWeek(semester=sem, week=1, monday=first_monday)
    wk.save()
    
    return sem
Example #2
0
def create_fake_semester(strm):
    """
    Create a close-enough Semester object for testing
    """
    strm = str(strm)
    if Semester.objects.filter(name=strm):
        return
    s = Semester(name=strm)
    yr = int(strm[0:3]) + 1900
    if strm[3] == '1':
        mo = 1
    elif strm[3] == '4':
        mo = 5
    elif strm[3] == '7':
        mo = 9

    s.start = datetime.date(yr, mo, 5)
    s.end = datetime.date(yr, mo + 3, 1)
    s.save()

    sw = SemesterWeek(semester=s, week=1)
    mon = s.start
    while mon.weekday() != 0:
        mon -= datetime.timedelta(days=1)
    sw.monday = mon
    sw.save()

    return s
Example #3
0
def create_fake_semester(strm):
    """
    Create a close-enough Semester object for testing
    """
    strm = str(strm)
    if Semester.objects.filter(name=strm):
        return
    s = Semester(name=strm)
    yr = int(strm[0:3]) + 1900
    if strm[3] == '1':
        mo = 1
    elif strm[3] == '4':
        mo = 5
    elif strm[3] == '7':
        mo = 9

    s.start = datetime.date(yr,mo,5)
    s.end = datetime.date(yr,mo+3,1)
    s.save()

    sw = SemesterWeek(semester=s, week=1)
    mon = s.start
    while mon.weekday() != 0:
        mon -= datetime.timedelta(days=1)
    sw.monday = mon
    sw.save()

    return s
Example #4
0
    def test_semester_2(self):
        s = create_semester()
        wk = SemesterWeek(semester=s, week=1, monday=date(2007,9,3))
        wk.save()
        wk = SemesterWeek(semester=s, week=5, monday=date(2007,10,8)) # pretend there is a Oct 1-5 break
        wk.save()

        # test due date calculations: convert date to week-of-semester and weekday (and back)
        tz = pytz.timezone('America/Vancouver')
        
        dt = datetime(2007, 9, 19, 23, 59, 59)
        self._test_due_date(s, dt, 3, 2)
        
        dt = datetime(2007, 11, 16, 16, 0, 0, tzinfo=tz) # timezone change between this and previous SemesterWeek
        self._test_due_date(s, dt, 10, 4)

        dt = datetime(2007, 11, 4, tzinfo=tz) # timezone change between this and previous Monday
        self._test_due_date(s, dt, 8, 6)

        dt = datetime(2007, 10, 10, tzinfo=tz) # right after a break
        self._test_due_date(s, dt, 5, 2)
        
        dt = datetime(2007, 10, 3, tzinfo=tz) # during a break
        # shouldn't be inverse function here: duedate always returns an in-semester date
        self._test_due_date(s, dt, 5, 2, reverse=datetime(2007,10,10, tzinfo=tz))

        wk, wkday = s.week_weekday(date(2007, 10, 3))
        self.assertEqual(wk, 5)
        self.assertEqual(wkday, 2)

        # check weird special-case for before-the-start dates
        self.assertEqual(s.week_weekday(date(2007, 9, 2)), (1, 0))
Example #5
0
    def test_semester(self):
        """
        Create and test a semester object
        """
        s = create_semester()
        wk = SemesterWeek(semester=s, week=1, monday=date(2007,9,3))
        wk.save()
        wk = SemesterWeek(semester=s, week=5, monday=date(2007,10,8)) # pretend there is a Oct 1-5 break
        wk.save()
        
        self.assertEquals(s.label(), "Fall 2007")
        self.assertEquals(str(wk), "1077 week 5")

        # test semester arithmetic
        s = Semester.objects.get(name='1131')
        self.assertEqual(s.previous_semester().name, '1127')
        self.assertEqual(s.offset(1).name, '1134')
        self.assertEqual(s.offset(-1).name, '1127')
        self.assertEqual(s.offset(2).name, '1137')
        self.assertEqual(s.offset(-2).name, '1124')
        self.assertEqual(s - s.offset(-2), 2)
        self.assertEqual(s.offset(-2) - s, -2)

        self.assertEqual(s.offset_name(1), '1134')
        self.assertEqual(s.offset_name(-1), '1127')
        self.assertEqual(s.offset_name(2), '1137')
        self.assertEqual(s.offset_name(-2), '1124')
        self.assertEqual(s.offset_name(3), '1141')
        self.assertEqual(s.offset_name(-3), '1121')
        self.assertEqual(s.offset_name(4), '1144')
        self.assertEqual(s.offset_name(-4), '1117')

        s2 = Semester(name="1077", start=date(2007,9,4), end=date(2007,12,3))
        self.assertRaises(IntegrityError, s2.save)
Example #6
0
def import_semester_info(verbose=False, dry_run=False, long_long_ago=False, bootstrap=False):
    """
    Update information on Semester objects from SIMS

    Finding the reference is tricky. Try Googling 'sfu calendar {{year}} "academic dates"'

    long_long_ago: import from the beginning of time
    bootstrap: don't assume Semester.current() will work, for bootstrapping test data creation
    """
    output = []
    semester_start = semester_first_day()
    semester_end = semester_last_day()
    sims_holidays = [(datetime.datetime.strptime(d, "%Y-%m-%d").date(), h) for d,h in all_holidays()]

    if not bootstrap:
        # we want semesters 5 years into the future: that's a realistic max horizon for grad promises
        current = Semester.current()
        strms = [current.offset_name(i) for i in range(15)]
    else:
        strms = []

    if long_long_ago:
        strms = sorted(list(set(strms) | set(semester_start.keys())))
    semesters = dict((s.name, s) for s in Semester.objects.filter(name__in=strms))

    semester_weeks = itertools.groupby(
                SemesterWeek.objects.filter(semester__name__in=strms).select_related('semester'),
                lambda sw: sw.semester.name)
    semester_weeks = dict((k,list(v)) for k,v in semester_weeks)

    holidays = itertools.groupby(
                Holiday.objects.filter(semester__name__in=strms, holiday_type='FULL').select_related('semester'),
                lambda h: h.semester.name)
    holidays = dict((k,list(v)) for k,v in holidays)

    for strm in strms:
        url = settings.BASE_ABS_URL + reverse('sysadmin:edit_semester', kwargs={'semester_name': strm})

        # Semester object
        try:
            semester = semesters[strm]
        except KeyError:
            semester = Semester(name=strm)
            semesters[strm] = semester
            output.append("Creating %s." % (strm,))

        # class start and end dates
        try:
            start = datetime.datetime.strptime(semester_start[strm], "%Y-%m-%d").date()
        except KeyError:
            # No data found about this semester: if there's a date already around, honour it
            # Otherwise, guess "same day as this semester last year" which is probably wrong but close.
            start = semester.start
            if not semester.start:
                lastyr = semesters[semester.offset_name(-3)]
                start = lastyr.start.replace(year=lastyr.start.year+1)
                output.append("Guessing start date for %s." % (strm,))

        try:
            end = datetime.datetime.strptime(semester_end[strm], "%Y-%m-%d").date()
        except KeyError:
            # no classes scheduled yet? Assume 13 weeks exactly
            end = start + datetime.timedelta(days=91)

        if semester.start != start:
            output.append("Changing start date for %s from %s to %s." % (strm, semester.start, start))
            semester.start = start
        if semester.end != end:
            output.append("Changing end date for %s from %s to %s." % (strm, semester.end, end))
            semester.end = end

        if not dry_run:
            semester.save()

        # SemesterWeeks
        weeks = semester_weeks.get(strm, [])
        if not weeks:
            sw = SemesterWeek(semester=semester, week=1, monday=first_monday(start))
            weeks.append(sw)
            assert sw.monday.weekday() == 0
            output.append("Creating week 1 for %s on %s." % (strm, sw.monday))
            if not dry_run:
                sw.save()
        elif weeks[0].monday != first_monday(start):
            sw = weeks[0]
            sw.monday = first_monday(start)
            output.append("Changing first Monday of %s to %s." % (strm, sw.monday))
            if not dry_run:
                sw.save()

        length = semester.end - semester.start
        if not bootstrap and length > datetime.timedelta(days=92) and len(weeks) < 2 \
                and semester.start - datetime.date.today() < datetime.timedelta(days=365):
            # semester is longer than 13 weeks: insist that the user specify reading week reasonably-soon before the semester starts
            message = "Semester %s is long (%s) but has no reading week specified. Please have a look here: %s\n\nYou probably want to enter the Monday of week 5/6/7/8 as the Monday after reading week, a week later than it would otherwise be." % (strm, length, url)
            if verbose:
                output.append('*** ' + message)
            else:
                import_admin_email(source='coredata.importer.import_semester_info', message=message)
        elif not bootstrap:
            # also check that the last day of classes is at a coherent time. Might reveal problems with reading week specification.
            endweek,_ = semester.week_weekday(semester.end, weeks=weeks)
            if endweek not in [12, 13, 14]:
                message = "Semester %s ends in week %i (should be 13 or 14). That's weird. Have a look here to see if things are coherent: %s" % (strm, endweek, url)
                if verbose:
                    output.append('*** ' + message)
                else:
                    import_admin_email(source='coredata.importer.import_semester_info', message=message)

        # Holidays
        hs = holidays.get(strm, [])
        h_start, h_end = Semester.start_end_dates(semester)
        for dt, desc in [(d,h) for d,h in sims_holidays if h_start <= d <= h_end]:
            existing = [h for h in hs if h.date == dt]
            if existing:
                holiday = existing[0]
            else:
                holiday = Holiday(semester=semester, date=dt, holiday_type='FULL')
                output.append("Adding holiday %s on %s." % (desc, dt))

            holiday.description = desc
            if not dry_run:
                holiday.save()



    if verbose:
        print '\n'.join(output)
Example #7
0
def import_semester_info(verbose=False, dry_run=False, long_long_ago=False, bootstrap=False):
    """
    Update information on Semester objects from SIMS

    Finding the reference is tricky. Try Googling 'sfu calendar {{year}} "academic dates"'

    long_long_ago: import from the beginning of time
    bootstrap: don't assume Semester.current() will work, for bootstrapping test data creation
    """
    output = []
    semester_start = semester_first_day()
    semester_end = semester_last_day()
    sims_holidays = all_holidays()

    if not bootstrap:
        # we want semesters 5 years into the future: that's a realistic max horizon for grad promises
        current = Semester.current()
        strms = [current.offset_name(i) for i in range(15)]
    else:
        strms = []

    if long_long_ago:
        strms = sorted(list(set(strms) | set(semester_start.keys())))
    semesters = dict((s.name, s) for s in Semester.objects.filter(name__in=strms))

    semester_weeks = itertools.groupby(
                SemesterWeek.objects.filter(semester__name__in=strms).select_related('semester'),
                lambda sw: sw.semester.name)
    semester_weeks = dict((k,list(v)) for k,v in semester_weeks)

    holidays = itertools.groupby(
                Holiday.objects.filter(semester__name__in=strms, holiday_type='FULL').select_related('semester'),
                lambda h: h.semester.name)
    holidays = dict((k,list(v)) for k,v in holidays)

    for strm in strms:
        url = settings.BASE_ABS_URL + reverse('sysadmin:edit_semester', kwargs={'semester_name': strm})

        # Semester object
        try:
            semester = semesters[strm]
        except KeyError:
            semester = Semester(name=strm)
            semesters[strm] = semester
            output.append("Creating %s." % (strm,))

        # class start and end dates
        try:
            start = semester_start[strm]
        except KeyError:
            # No data found about this semester: if there's a date already around, honour it
            # Otherwise, guess "same day as this semester last year" which is probably wrong but close.
            start = semester.start
            if not semester.start:
                lastyr = semesters[semester.offset_name(-3)]
                start = lastyr.start.replace(year=lastyr.start.year+1)
                output.append("Guessing start date for %s." % (strm,))

        try:
            end = semester_end[strm]
        except KeyError:
            # no classes scheduled yet? Assume 13 weeks exactly
            end = start + datetime.timedelta(days=91)

        if semester.start != start:
            output.append("Changing start date for %s from %s to %s." % (strm, semester.start, start))
            semester.start = start
        if semester.end != end:
            output.append("Changing end date for %s from %s to %s." % (strm, semester.end, end))
            semester.end = end

        if not dry_run:
            semester.save()

        # SemesterWeeks
        weeks = semester_weeks.get(strm, [])
        if not weeks:
            sw = SemesterWeek(semester=semester, week=1, monday=first_monday(start))
            weeks.append(sw)
            assert sw.monday.weekday() == 0
            output.append("Creating week 1 for %s on %s." % (strm, sw.monday))
            if not dry_run:
                sw.save()
        elif weeks[0].monday != first_monday(start):
            sw = weeks[0]
            sw.monday = first_monday(start)
            output.append("Changing first Monday of %s to %s." % (strm, sw.monday))
            if not dry_run:
                sw.save()

        length = semester.end - semester.start
        if not bootstrap and length > datetime.timedelta(days=92) and len(weeks) < 2 \
                and semester.start - datetime.date.today() < datetime.timedelta(days=365):
            # semester is longer than 13 weeks: insist that the user specify reading week reasonably-soon before the semester starts
            message = "Semester %s is long (%s) but has no reading week specified. Please have a look here: %s\n\nYou probably want to enter the Monday of week 5/6/7/8 as the Monday after reading week, a week later than it would otherwise be." % (strm, length, url)
            if verbose:
                output.append('*** ' + message)
            else:
                import_admin_email(source='coredata.importer.import_semester_info', message=message)
        elif not bootstrap:
            # also check that the last day of classes is at a coherent time. Might reveal problems with reading week specification.
            endweek,_ = semester.week_weekday(semester.end, weeks=weeks)
            if endweek not in [12, 13, 14]:
                message = "Semester %s ends in week %i (should be 13 or 14). That's weird. Have a look here to see if things are coherent: %s" % (strm, endweek, url)
                if verbose:
                    output.append('*** ' + message)
                else:
                    import_admin_email(source='coredata.importer.import_semester_info', message=message)

        # Holidays
        hs = holidays.get(strm, [])
        h_start, h_end = Semester.start_end_dates(semester)
        for dt, desc in [(d,h) for d,h in sims_holidays if h_start <= d <= h_end]:
            existing = [h for h in hs if h.date == dt]
            if existing:
                holiday = existing[0]
            else:
                holiday = Holiday(semester=semester, date=dt, holiday_type='FULL')
                output.append("Adding holiday %s on %s." % (desc, dt))

            holiday.description = desc
            if not dry_run:
                holiday.save()



    if verbose:
        print('\n'.join(output))