@@ -35,9 +35,7 @@ def __init__(self, *args, **kwargs):
3535 return
3636
3737 # show the window
38- # chapter14: use after() here to eliminate the small window
39- # that flashes up breifly
40- self .after (250 , self .deiconify )
38+ self .deiconify ()
4139
4240 # Create model
4341 # remove for ch12
@@ -66,7 +64,7 @@ def __init__(self, *args, **kwargs):
6664 '<<NewRecord>>' : self ._new_record ,
6765 '<<UpdateWeatherData>>' : self ._update_weather_data ,
6866 '<<UploadToCorporateREST>>' : self ._upload_to_corporate_rest ,
69- '<<UploadToCorporateFTP >>' : self ._upload_to_corporate_ftp ,
67+ '<<UploadToCorporateSFTP >>' : self ._upload_to_corporate_sftp ,
7068 }
7169 for sequence , callback in event_callbacks .items ():
7270 self .bind (sequence , callback )
@@ -98,9 +96,8 @@ def __init__(self, *args, **kwargs):
9896
9997 # The data record list
10098 self .recordlist_icon = tk .PhotoImage (file = images .LIST_ICON )
101- self .recordlist = v .RecordList (
102- self , self .inserted_rows , self .updated_rows
103- )
99+ self .recordlist = v .RecordList (self )
100+
104101 self .notebook .insert (
105102 0 , self .recordlist , text = 'Records' ,
106103 image = self .recordlist_icon , compound = tk .LEFT
@@ -287,12 +284,13 @@ def _set_font(self, *_):
287284 tk_font .config (size = font_size , family = font_family )
288285
289286 # new chapter 13
290- def _update_weather_data (self ):
287+ def _update_weather_data (self , * _ ):
291288 """Initiate retrieval and storage of weather data"""
289+ weather_data_model = m .WeatherDataModel (
290+ self .settings ['weather_station' ].get ()
291+ )
292292 try :
293- weather_data = n .get_local_weather (
294- self .settings ['weather_station' ].get ()
295- )
293+ weather_data = weather_data_model .get_weather_data ()
296294 except Exception as e :
297295 messagebox .showerror (
298296 title = 'Error' ,
@@ -301,80 +299,170 @@ def _update_weather_data(self):
301299 )
302300 self .status .set ('Problem retrieving weather data' )
303301 else :
304- self .data_model .add_weather_data (weather_data )
302+ self .model .add_weather_data (weather_data )
305303 time = weather_data ['observation_time_rfc822' ]
306304 self .status .set (f"Weather data recorded for { time } " )
307305
308306 def _create_csv_extract (self ):
309307 csvmodel = m .CSVModel ()
310308 records = self .model .get_all_records ()
311309 if not records :
312- return None
310+ raise Exception ( 'No records were found to build a CSV file.' )
313311 for record in records :
314312 csvmodel .save_record (record )
315313 return csvmodel .file
316314
317- def _upload_to_corporate_ftp (self , * _ ):
318315
319- csvfile = self ._create_csv_extract ()
320- d = v .LoginDialog (self , 'Login to ABQ Corporate FTP' )
316+ def _upload_to_corporate_sftp (self , * _ ):
317+
318+ # create csv file
319+ try :
320+ csvfile = self ._create_csv_extract ()
321+ except Exception as e :
322+ messagebox .showwarning (
323+ title = 'Error' , message = str (e )
324+ )
325+ return
326+
327+ # authenticate
328+ d = v .LoginDialog (self , 'Login to ABQ Corporate SFTP' )
321329 if d .result is None :
322330 return
323331 username , password = d .result
324- host = self .settings ['abq_ftp_host' ].get ()
325- port = self .settings ['abq_ftp_port' ].get ()
332+
333+ # create model
334+ host = self .settings ['abq_sftp_host' ].get ()
335+ port = self .settings ['abq_sftp_port' ].get ()
336+ sftp_model = m .SFTPModel (host , port )
326337 try :
327- n .upload_to_corporate_ftp (
328- csvfile , host , port , username , password
329- )
330- except n .ftp .all_errors as e :
331- messagebox .showerror ('Error Uploading File.' , str (e ))
338+ sftp_model .authenticate (username , password )
339+ except Exception as e :
340+ messagebox .showerror ('Error Authenticating' , str (e ))
332341 return
342+
343+ # check destination file
344+ destination_dir = self .settings ['abq_sftp_path' ].get ()
345+ destination_path = f'{ destination_dir } /{ csvfile .name } '
346+
333347 try :
334- files = n .get_corporate_ftp_files (
335- host , port , username , password
336- )
337- except n .ftp .all_errors as e :
348+ exists = sftp_model .check_file (destination_path )
349+ except Exception as e :
338350 messagebox .showerror (
339- 'Error listing Files ( file uploaded OK) ' ,
351+ f 'Error checking file { destination_path } ' ,
340352 str (e )
341353 )
342354 return
343- filestring = '\n ' .join (f'* { f } ' for f in files )
344- messagebox .showinfo (
345- 'Success' , f'{ csvfile } successfully uploaded to FTP \n \n '
346- f'Current files on the server are: \n \n { filestring } '
347- )
355+ if exists :
356+ # ask if we should overwrite
357+ overwrite = messagebox .askyesno (
358+ 'File exists' ,
359+ f'The file { destination_path } already exists on the server, '
360+ 'do you want to overwrite it?'
361+ )
362+ if not overwrite :
363+ # ask if we should download it
364+ download = messagebox .askyesno (
365+ 'Download file' ,
366+ 'Do you want to download the file to inspect it?'
367+ )
368+ if download :
369+ # get a destination filename and save
370+ filename = filedialog .asksaveasfilename ()
371+ if not filename :
372+ return
373+ try :
374+ sftp_model .get_file (destination_path , filename )
375+ except Exception as e :
376+ messagebox .showerror ('Error downloading' , str (e ))
377+ return
378+ messagebox .showinfo (
379+ 'Download Complete' , 'Download Complete.'
380+ )
381+ return
382+ # if we haven't returned, the user wants to upload
383+ try :
384+ sftp_model .upload_file (csvfile , destination_path )
385+ except Exception as e :
386+ messagebox .showerror ('Error uploading' , str (e ))
387+ else :
388+ messagebox .showinfo (
389+ 'Success' ,
390+ f'{ csvfile } successfully uploaded to SFTP server.'
391+ )
348392
349393 def _upload_to_corporate_rest (self , * _ ):
350- csvfile = self ._create_csv_extract ()
351- if csvfile is None :
394+
395+ # create csv file
396+ try :
397+ csvfile = self ._create_csv_extract ()
398+ except Exception as e :
352399 messagebox .showwarning (
353- title = 'No records' ,
354- message = 'There are no records to upload'
400+ title = 'Error' , message = str (e )
355401 )
356402 return
403+
404+ # Authenticate to the rest server
357405 d = v .LoginDialog (
358406 self , 'Login to ABQ Corporate REST API'
359407 )
360408 if d .result is not None :
361409 username , password = d .result
362410 else :
363411 return
364- self .rest_queue = Queue ()
365- uploader = n .CorporateRestUploader (
366- csvfile ,
367- self .settings ['abq_upload_url' ].get (),
368- self .settings ['abq_auth_url' ].get (),
369- username ,
370- password ,
371- self .rest_queue
412+
413+ # create REST model
414+ rest_model = m .CorporateRestModel (
415+ self .settings ['abq_rest_url' ].get ()
372416 )
373- uploader .start ()
374- self ._check_queue (self .rest_queue )
417+ try :
418+ rest_model .authenticate (username , password )
419+ except Exception as e :
420+ messagebox .showerror ('Error authenticating' , str (e ))
421+ return
422+
423+ # Check if the file exists
424+ try :
425+ exists = rest_model .check_file (csvfile .name )
426+ except Exception as e :
427+ messagebox .showerror ('Error checking for file' , str (e ))
428+ return
429+
430+ if exists :
431+ # ask if we should overwrite
432+ overwrite = messagebox .askyesno (
433+ 'File exists' ,
434+ f'The file { csvfile .name } already exists on the server, '
435+ 'do you want to overwrite it?'
436+ )
437+ if not overwrite :
438+ # ask if we should download it
439+ download = messagebox .askyesno (
440+ 'Download file' ,
441+ 'Do you want to download the file to inspect it?'
442+ )
443+ if download :
444+ # get a destination filename and save
445+ filename = filedialog .asksaveasfilename ()
446+ if not filename :
447+ return
448+ try :
449+ data = rest_model .get_file (csvfile .name )
450+ except Exception as e :
451+ messagebox .showerror ('Error downloading' , str (e ))
452+ return
453+ with open (filename , 'w' , encoding = 'utf-8' ) as fh :
454+ fh .write (data )
455+ messagebox .showinfo (
456+ 'Download Complete' , 'Download Complete.'
457+ )
458+ return
459+ # if we haven't returned, the user wants to upload
460+ rest_model .upload_file (csvfile )
461+ self ._check_queue (rest_model .queue )
462+
375463
376464 def _check_queue (self , queue ):
377- if not queue .empty ():
465+ while not queue .empty ():
378466 item = queue .get ()
379467 if item .status == 'done' :
380468 messagebox .showinfo (
@@ -393,5 +481,5 @@ def _check_queue(self, queue):
393481 self .status .set (item .subject )
394482 return
395483 else :
396- self .status .set (item .body )
484+ self .status .set (f' { item .subject } : { item . body } ' )
397485 self .after (100 , self ._check_queue , queue )
0 commit comments