44from pprint import pprint
55
66from fet_api_to_gcal import db
7- from fet_api_to_gcal .common .utils import getDate , perror , psuccess , path_leaf
7+ from fet_api_to_gcal .common .utils import (error_str , getDate , info_str ,
8+ path_leaf , perror , psuccess ,
9+ success_str , timestamped_filename )
810from fet_api_to_gcal .models import Calendar , Resource , Std_mail , Teacher
911
10-
1112# TODO: add proper logging to the script. (file + stdout).
1213# TODO: add an arguemt parser to script.
1314
14-
15-
1615dates = {
1716 "2CPI" : "2020/02/23" , # ! needs to be changed accordingly!
18- "1CS" : "2020/02/23" , # ! needs to be changed accordingly!
19- "2CS" : "2020/02/23" , # ! needs to be changed accordingly!
20- "3CS" : "2020/02/23" , # ! needs to be changed accordingly!
17+ "1CS" : "2020/02/23" , # ! needs to be changed accordingly!
18+ "2CS" : "2020/02/23" , # ! needs to be changed accordingly!
19+ "3CS" : "2020/02/23" , # ! needs to be changed accordingly!
2120 "1CPI" : "2020/02/23" , # ! needs to be changed accordingly!
2221}
2322
@@ -41,8 +40,31 @@ def check_timetable_validity(timetable_path,
4140 list: list of google styled events, each google event is a python dictionary.
4241 """
4342
43+ # SETUP LOGGING
44+
45+ log_filename = timestamped_filename (filename = path_leaf (timetable_path ))
46+
47+ logging .basicConfig (
48+ level = logging .DEBUG ,
49+ format = '%(asctime)s %(name)-12s %(levelname)-8s %(message)s' ,
50+ datefmt = '%m-%d %H:%M:%S' ,
51+ filename = "./logs/{}_checker_script.log" .format (log_filename ),
52+ filemode = 'w' )
53+
54+ console = logging .StreamHandler ()
55+ console .setLevel (logging .WARNING )
56+ formatter = logging .Formatter ('%(name)-12s: %(levelname)-8s %(message)s' )
57+ console .setFormatter (formatter )
58+ logging .getLogger ('' ).addHandler (console )
59+ logging .info (info_str ("Started logging in file {}" .format (log_filename )))
60+
4461 timezone = "Africa/Algiers"
45- f = open (timetable_path , "r" )
62+ try :
63+ f = open (timetable_path , "r" )
64+ except Exception as e :
65+ logging .exception (
66+ error_str ("Exception while opening file {}" .format (
67+ path_leaf (timetable_path ))))
4668 lines = f .readlines ()[1 ::]
4769 all_events = [] # to hold all json gevents later!
4870 temp_dict_holder = {}
@@ -80,14 +102,17 @@ def check_timetable_validity(timetable_path,
80102
81103 # ? 2nd phase
82104
83-
84105 # ? indexes are used to allow non-ordered events to be generated successfully.
106+ logging .info (info_str ("Started converting event to google events" ))
85107 indexes = list (map (int , list (temp_dict_holder .keys ())))
86108 for event_inx in indexes :
87109 try :
88110 event___old = temp_dict_holder [str (event_inx )]
89111 except KeyError as e :
90- print (e )
112+ logging .exception (
113+ error_str (
114+ "Exception in event at index {} thus will not be added" .
115+ format (event_inx )))
91116 __gevent__ = {"summary" : event___old ["summary" ]}
92117
93118 # ? get attendees emails
@@ -99,20 +124,29 @@ def check_timetable_validity(timetable_path,
99124 __gevent__ ["attendees" ].append (
100125 {"email" : teacher .teacher_email })
101126 else :
102- perror ("Teacher {} not found (event index: {})" .format (
103- teacher_name , event_inx ))
127+ logging .warning (
128+ error_str ("Teacher {} not found (event index: {})" .format (
129+ teacher_name , event_inx )))
104130
105- # students
131+ # students (important part)
106132 if event___old ["std_set" ] == "" :
107- perror ("Std_set empty in event index : {}" .format (event_inx ))
108- #pprint(event___old)
133+ logging .error (
134+ error_str (
135+ "Std_set empty in event index : {}, thus event is ignored" .
136+ format (event_inx )))
109137 continue
138+
110139 for std_set__ in event___old ["std_set" ].split ("+" ):
111140
112141 std_mails_obj = Std_mail .query .filter_by (std_set = std_set__ ).first ()
113142 if std_mails_obj is not None :
114143 __gevent__ ["attendees" ].append (
115144 {"email" : std_mails_obj .std_email })
145+ else :
146+ logging .error (
147+ error_str (
148+ "No Mapped email found for {}, thus calendar for it will be ignored"
149+ .format (std_set__ )))
116150
117151 # add room if existing
118152
@@ -124,15 +158,18 @@ def check_timetable_validity(timetable_path,
124158 "email" : res .resource_email ,
125159 "resource" : True
126160 })
161+ else :
162+ logging .warning (
163+ error_str ("Room {} not found in database" .format (
164+ event___old ["room" ])))
127165 else :
128- perror ("Room empty in event index : {}" .format (event_inx ))
129- #continue
130- # recurrence rule
166+ logging .warning (
167+ error_str ("Room at event index {} is empty" .format (event_inx )))
168+
169+ # ? recurrence rule
131170 __gevent__ ["recurrence" ] = [
132171 "RRULE:FREQ=WEEKLY;COUNT=" + str (events_freq )
133172 ]
134- # set start and time
135- # print(event___old["std_set"].split(" ")[0])
136173 dateTime_start = getDate (dates , event___old ["std_set" ].split (" " )[0 ],
137174 event___old ["Day" ],
138175 event___old ["start" ].split ("h" )[0 ],
@@ -152,18 +189,47 @@ def check_timetable_validity(timetable_path,
152189 all_events .append (__gevent__ )
153190
154191 if len (all_events ) == max_events :
192+ logging .info (
193+ success_str (
194+ "Converted {} events successfully (check log for warnings, if any)"
195+ .format (max_events )))
155196 return all_events
197+ logging .info (
198+ success_str (
199+ "Converted {} events successfully (check log for warnings, if any)"
200+ .format (len (all_events ))))
156201 return all_events
157202
158203
159204def check_google_event (gevent ):
160-
205+ """Checks if a google calendar object can be sent to the API without any errors/.\
206+ So, any errors would be either from the API itself or the network status.
207+
208+ Args:
209+ gevent (dict): A google calendar event
210+
211+ Raises:
212+ NotImplementedError: Obviously, this is not yet implemented, daah!
213+ """
161214 raise NotImplementedError
162215
163216
164217if __name__ == "__main__" :
165- tt_path = sys .argv [1 ]
166- all_events = check_timetable_validity (timetable_path = tt_path )
218+ # ? create an arguemnt parser
219+ parser = argparse .ArgumentParser (
220+ description = "Script to check FET timetable file for any errors/warnings before running the import" \
221+ " operation from the web app" )
222+ parser .add_argument ("-f" ,
223+ "--file" ,
224+ type = str ,
225+ metavar = 'Path' ,
226+ dest = 'file' ,
227+ help = "Path to the FET generated timetable CSV file." )
228+
229+ # ? Parse arguments
230+ args = parser .parse_args ()
231+ tt_path = args .file
232+ all_events = check_timetable_validity (timetable_path = tt_path , dates = dates )
167233 for event in all_events :
168234 resource = None
169235 teachers = []
@@ -188,10 +254,6 @@ def check_google_event(gevent):
188254 std_email = std_mail ["email" ]).first ()
189255 if cal_rec :
190256 calendar_id = cal_rec .calendar_id_google
191- """
192- #import pdb; pdb.set_trace()
193- """
194257 else :
195- print ("Calendar does not exist" )
196- print ("_________" )
258+ perror ("Calendar does not exist, check please" )
197259 continue
0 commit comments