Browse Source

code cleanup/style improvements

Justin Tracey 3 years ago
parent
commit
0e0580571d
1 changed files with 86 additions and 76 deletions
  1. 86 76
      calendar.py

+ 86 - 76
calendar.py

@@ -1,20 +1,21 @@
 #!/usr/bin/env python3
 from datetime import date,timedelta
-import sys
-import argparse
+import sys, argparse
 
 def str_to_date(string_date):
     return date(*[int(s) for s in string_date.split('-')])
 
 class CryspCalendar:
     """Representation of a CrySP weekly meeting schedule for a term"""
-    def __init__(self, start, end=None, weeks=None, names=[],\
-                 constraints=[], practice_talks=[], half_practices=[], notes=[], no_repeat=False):
+    def __init__(self, start, end=None, weeks=None, names=[],
+                 constraints=[], practice_talks=[], half_practices=[], notes=[],
+                 no_repeat=False):
         self.dates = self.meeting_dates(start, end, weeks)
         self.names = names
         self.constraints = self.parse_constraints(constraints)
         self.practice_talks      = self.parse_practice_talks(practice_talks)
-        self.practice_talks.update(self.parse_practice_talks(half_practices, half=True))
+        self.practice_talks.update(self.parse_practice_talks(half_practices,
+                                                             half=True))
         self.notes      = self.parse_notes(notes)
         self.notes.update(self.parse_notes(practice_talks))
         self.notes.update(self.parse_notes(half_practices))
@@ -27,7 +28,8 @@ class CryspCalendar:
         if end:
             last_meeting = str_to_date(end)
         if weeks:
-            last_meeting = max(first_meeting + timedelta(weeks=weeks), last_meeting)
+            last_meeting = max(first_meeting + timedelta(weeks=weeks),
+                               last_meeting)
         ret = []
         next_meeting = first_meeting
         one_week = timedelta(weeks=1)
@@ -54,13 +56,13 @@ class CryspCalendar:
             day  = str_to_date(talk[1])
             if day in practice_dict:
                 assert half,\
-                    "conflicting talks: %s and %s on %s" %\
+                    'conflicting talks: %s and %s on %s' %\
                     (practice_dict[day][0], name, day)
                 practice_dict[day].append(name)
             elif half:
                 practice_dict[day] = [name,]
             else:
-                practice_dict[day] = [name, ""]
+                practice_dict[day] = [name, '']
         return practice_dict
 
     def parse_notes(self, notes):
@@ -78,11 +80,11 @@ class CryspCalendar:
         for name in self.constraints:
             for day in self.constraints[name]:
                 assert day in self.dates,\
-                    "constraint added for %s on %s, which is not a meeting date" %\
+                    'constraint added for %s on %s, which is not a meeting date' %\
                     (name, day)
         for day in self.practice_talks:
             assert day in self.dates,\
-                "talk by %s designated on %s, which is not a meeting date" %\
+                'talk by %s designated on %s, which is not a meeting date' %\
                 (self.practice_talks[day][0], day)
         for day in self.notes:
             assert day in self.dates,\
@@ -90,6 +92,9 @@ class CryspCalendar:
                 (self.notes[day], day)
 
     def pop_name(self, day, names, i):
+        """Pops the name of the next available on day from the names stack,
+           where 'i' is which speaker they would be for that day (0 or 1).
+           Returns None if no speakers are left in the given names stack."""
         name = None
         if day in self.practice_talks:
             if i < len(self.practice_talks[day]):
@@ -104,6 +109,7 @@ class CryspCalendar:
         return name
 
     def next_speaker(self, day, names, i):
+        """Wrapper for pop_name() that repopulates names stack if needed."""
         name = self.pop_name(day, names, i)
         if name or self.no_repeat:
             return name
@@ -113,26 +119,26 @@ class CryspCalendar:
     def date_to_speakers(self, day, names):
         speaker1 = self.next_speaker(day, names, 0)
         speaker2 = self.next_speaker(day, names, 1)
-        note = self.notes.get(day, "")
+        note = self.notes.get(day, '')
         return speaker1, speaker2, note
 
-    # returns a string containing a twiki table
     def table(self):
-        table = "| *Date* | *Speakers* | *Notes* |\n"
+        """Returns a string containing a twiki table."""
+        table = '| *Date* | *Speakers* | *Notes* |\n'
         names = self.names.copy()
         for day in self.dates:
-            table += day.strftime("| %b %e |")
+            table += day.strftime('| %b %e |')
             speaker1, speaker2, note = self.date_to_speakers(day, names)
             if speaker1:
                 table += ' ' + speaker1
             if speaker2:
-                table += ", " + speaker2
-            table += " | " + note + " |\n"
+                table += ', ' + speaker2
+            table += ' | ' + note + ' |\n'
         return table
 
-    # returns a string containing the currently used email layout, filled in
     def email(self, weeks=2, today=date.today()):
-        emailstr = ""
+        """Returns a string for emailing to the lab who is speaking next"""
+        emailstr = ''
         names = self.names.copy()
         i = 0
         for day in self.dates:
@@ -143,73 +149,77 @@ class CryspCalendar:
             if i > weeks:
                 break
             speaker1, speaker2, note = self.date_to_speakers(day, names)
-            emailstr += day.strftime("%b %e: ")
+            emailstr += day.strftime('%b %e: ')
             if speaker1:
                 emailstr += speaker1
                 if speaker2:
-                    emailstr +=  ", " + speaker2
-                if note != "":
-                    emailstr += " (" + note + ")"
+                    emailstr +=  ', ' + speaker2
+                if note != '':
+                    emailstr += ' (' + note + ')'
             else:
                 emailstr += note
-            emailstr += "\n"
-        emailstr += "\nhttps://cs.uwaterloo.ca/twiki/view/CrySP/SpeakerSchedule\n"
+            emailstr += '\n'
+        emailstr += '\nhttps://cs.uwaterloo.ca/twiki/view/CrySP/SpeakerSchedule\n'
         return emailstr
 
 def parse_constraintsfile(filename):
-    f = open(filename, 'r')
-    tweaks = {'c': [], 'p': [], 'h': [], 'n': []}
-    for line in f:
-        l = [x.strip() for x in line.rstrip().split(',')]
-        tweaks[l[0]].append(l[1:])
-    return tweaks['c'], tweaks['p'], tweaks['h'], tweaks['n']
+    with open(filename, 'r') as f:
+        tweaks = {'c': [], 'p': [], 'h': [], 'n': []}
+        for line in f:
+            l = [x.strip() for x in line.rstrip().split(',')]
+            tweaks[l[0]].append(l[1:])
+        return tweaks['c'], tweaks['p'], tweaks['h'], tweaks['n']
 
 def make_parser():
     parser = argparse.ArgumentParser(description = \
-                                     "Print a speaker schedule for the CrySP weekly meetings.")
-    parser.add_argument("-s", "--start",
-                        metavar = "DATE", required = True,
-                        help = "date of the first meeting in ISO format (yyyy-mm-dd)")
-    parser.add_argument("-e", "--end", metavar = "DATE",
-                        help = "last date to schedule a meeting on or before " +\
-                        "(if -w also specified, uses whatever is shortest)")
-    parser.add_argument("-w", "--weeks", type=int,
-                        help = "number of weeks to schedule for " +\
-                        "(if -e also specified, uses whatever is shortest)")
+        'Print a speaker schedule for the CrySP weekly meetings.')
+    parser.add_argument('-s', '--start',
+                        metavar = 'DATE', required = True,
+                        help = 'date of the first meeting in ISO format ' +\
+                        '(yyyy-mm-dd)')
+    parser.add_argument('-e', '--end', metavar = 'DATE',
+                        help = 'last date to schedule a meeting on or before ' +\
+                        '(if -w also specified, uses whatever is shortest)')
+    parser.add_argument('-w', '--weeks', type=int,
+                        help = 'number of weeks to schedule for ' +\
+                        '(if -e also specified, uses whatever is shortest)')
 
     group = parser.add_mutually_exclusive_group()
-    group.add_argument("-n", "--names",
-                       nargs = '+', default = [], metavar = "NAME",
-                       help = "names to schedule in their speaking order")
-    group.add_argument("-f", "--namesfile",
-                       metavar = "FILE",
-                       help = "path of a file that contains a whitespace " +\
-                       "and/or comma seperated list of names to schedule in " +\
-                       "their speaking order")
-
-    parser.add_argument("-c", "--constraints",
-                        metavar = ("NAME", "DATES"),
-                        nargs = '+', action = "append", default = [],
-                        help = 'specify someone *can\'t* speak on certain dates ' +\
-                        '(e.g., "-c Justin 2018-01-01 2018-01-08 -c Ian 2018-01-01")')
-    parser.add_argument("-p", "--practice",
-                        metavar = ("NAME", "DATE", "NOTE"),
-                        nargs = 3, action = "append", default = [],
+    group.add_argument('-n', '--names',
+                       nargs = '+', default = [], metavar = 'NAME',
+                       help = 'names to schedule in their speaking order')
+    group.add_argument('-f', '--namesfile',
+                       metavar = 'FILE',
+                       help = 'path of a file that contains a whitespace ' +\
+                       'and/or comma seperated list of names to schedule in ' +\
+                       'their speaking order')
+
+    parser.add_argument('-c', '--constraints',
+                        metavar = ('NAME', 'DATES'),
+                        nargs = '+', action = 'append', default = [],
+                        help = "specify someone *can't* speak on certain " +\
+                        'dates (e.g., "-c Justin 2018-01-01 2018-01-08 -c ' +\
+                        'Ian 2018-01-01")')
+    parser.add_argument('-p', '--practice',
+                        metavar = ('NAME', 'DATE', 'NOTE'),
+                        nargs = 3, action = 'append', default = [],
                         help = 'designate given DATE as a talk given by NAME, '+\
-                        'and remove the next instance of NAME in the list of names, '+\
-                        'if present (NOTE should usually be "practice talk")')
-    parser.add_argument("-C", "--constraintsfile",
-                        metavar = "FILE",
-                        help = 'provide constraints, practice talks, and notes ' +\
-                        'via supplied csv file')
-
-    parser.add_argument("-r", "--no-repeat",
+                        'and remove the next instance of NAME in the list of '+\
+                        'names, if present (NOTE should usually be "practice '+\
+                        'talk")')
+    parser.add_argument('-C', '--constraintsfile',
+                        metavar = 'FILE',
+                        help = 'provide constraints, practice talks, and '+\
+                        'notes via supplied csv file')
+
+    parser.add_argument('-r', '--no-repeat',
                         action = 'store_true',
-                        help = "disables repeating the list of names")
-    parser.add_argument("-E", "--email",
-                        nargs='?', const=2, default=False, metavar="WEEKS",
-                        help = "print an email for notifying who is speaking" +\
-                        " the next two (or specified) weeks")
+                        help = 'disables repeating the list of names')
+    parser.add_argument('-E', '--email',
+                        nargs = '?', const = 2, default = False,
+                        metavar = 'WEEKS',
+                        help = 'print an email for notifying who is speaking' +\
+                        ' the next two (or specified) weeks')
     return parser
 
 def main(argv=None):
@@ -219,17 +229,17 @@ def main(argv=None):
     args = parser.parse_args()
 
     if not args.end and not args.weeks:
-        parser.error("requires -w/--weeks or -e/--end")
+        parser.error('requires -w/--weeks or -e/--end')
 
     if args.namesfile:
-        f = open(args.namesfile, 'r')
-        names = [x.strip() for x in f.read().split(',')]
-        f.close()
+        with open(args.namesfile, 'r') as f:
+            names = [x.strip() for x in f.read().split(',')]
     else:
         names = args.names
 
     if args.constraintsfile:
-        constraints, practice, halves, notes = parse_constraintsfile(args.constraintsfile)
+        constraints, practice, halves, notes = \
+            parse_constraintsfile(args.constraintsfile)
     else:
         constraints = args.constraints
         practice = args.practice
@@ -240,5 +250,5 @@ def main(argv=None):
     print(cal.table() if not args.email else cal.email(int(args.email)))
     return 0;
 
-if __name__ == "__main__":
+if __name__ == '__main__':
     sys.exit(main())