Skip to content

Commit f400417

Browse files
committed
Changes for rewrite of chapter 13
1 parent d2e6920 commit f400417

File tree

10 files changed

+2156
-120
lines changed

10 files changed

+2156
-120
lines changed

Chapter13/ABQ_Data_Entry/abq_data_entry/application.py

Lines changed: 130 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from . import models as m
1212
from .mainmenu import get_main_menu_for_os
1313
from . import images
14-
from . import network as n
1514

1615

1716
class Application(tk.Tk):
@@ -63,7 +62,7 @@ def __init__(self, *args, **kwargs):
6362
'<<NewRecord>>': self._new_record,
6463
'<<UpdateWeatherData>>': self._update_weather_data,
6564
'<<UploadToCorporateREST>>': self._upload_to_corporate_rest,
66-
'<<UploadToCorporateFTP>>': self._upload_to_corporate_ftp,
65+
'<<UploadToCorporateSFTP>>': self._upload_to_corporate_sftp,
6766
}
6867
for sequence, callback in event_callbacks.items():
6968
self.bind(sequence, callback)
@@ -286,10 +285,11 @@ def _set_font(self, *_):
286285
# new chapter 13
287286
def _update_weather_data(self, *_):
288287
"""Initiate retrieval and storage of weather data"""
288+
weather_data_model = m.WeatherDataModel(
289+
self.settings['weather_station'].get()
290+
)
289291
try:
290-
weather_data = n.get_local_weather(
291-
self.settings['weather_station'].get()
292-
)
292+
weather_data = weather_data_model.get_weather_data()
293293
except Exception as e:
294294
messagebox.showerror(
295295
title='Error',
@@ -306,70 +306,161 @@ def _create_csv_extract(self):
306306
csvmodel = m.CSVModel()
307307
records = self.model.get_all_records()
308308
if not records:
309-
return None
309+
raise Exception('No records were found to build a CSV file.')
310310
for record in records:
311311
csvmodel.save_record(record)
312312
return csvmodel.file
313313

314-
def _upload_to_corporate_ftp(self, *_):
315314

316-
csvfile = self._create_csv_extract()
317-
d = v.LoginDialog(self, 'Login to ABQ Corporate FTP')
315+
def _upload_to_corporate_sftp(self, *_):
316+
317+
# create csv file
318+
try:
319+
csvfile = self._create_csv_extract()
320+
except Exception as e:
321+
messagebox.showwarning(
322+
title='Error', message=str(e)
323+
)
324+
return
325+
326+
# authenticate
327+
d = v.LoginDialog(self, 'Login to ABQ Corporate SFTP')
318328
if d.result is None:
319329
return
320330
username, password = d.result
321-
host = self.settings['abq_ftp_host'].get()
322-
port = self.settings['abq_ftp_port'].get()
331+
332+
# create model
333+
host = self.settings['abq_sftp_host'].get()
334+
port = self.settings['abq_sftp_port'].get()
335+
sftp_model = m.SFTPModel(host, port)
323336
try:
324-
n.upload_to_corporate_ftp(
325-
csvfile, host, port, username, password
326-
)
327-
except n.ftp.all_errors as e:
328-
messagebox.showerror('Error Uploading File.', str(e))
337+
sftp_model.authenticate(username, password)
338+
except Exception as e:
339+
messagebox.showerror('Error Authenticating', str(e))
329340
return
341+
342+
# check destination file
343+
destination_dir = self.settings['abq_sftp_path'].get()
344+
destination_path = f'{destination_dir}/{csvfile.name}'
345+
330346
try:
331-
files = n.get_corporate_ftp_files(
332-
host, port, username, password
333-
)
334-
except n.ftp.all_errors as e:
347+
exists = sftp_model.check_file(destination_path)
348+
except Exception as e:
335349
messagebox.showerror(
336-
'Error listing Files (file uploaded OK)',
350+
f'Error checking file {destination_path}',
337351
str(e)
338352
)
339353
return
340-
filestring = '\n'.join(f'* {f}' for f in files)
341-
messagebox.showinfo(
342-
'Success', f'{csvfile} successfully uploaded to FTP \n\n'
343-
f'Current files on the server are: \n\n {filestring}'
344-
)
354+
if exists:
355+
# ask if we should overwrite
356+
overwrite = messagebox.askyesno(
357+
'File exists',
358+
f'The file {destination_path} already exists on the server, '
359+
'do you want to overwrite it?'
360+
)
361+
if not overwrite:
362+
# ask if we should download it
363+
download = messagebox.askyesno(
364+
'Download file',
365+
'Do you want to download the file to inspect it?'
366+
)
367+
if download:
368+
# get a destination filename and save
369+
filename = filedialog.asksaveasfilename()
370+
if not filename:
371+
return
372+
try:
373+
sftp_model.get_file(destination_path, filename)
374+
except Exception as e:
375+
messagebox.showerror('Error downloading', str(e))
376+
return
377+
messagebox.showinfo(
378+
'Download Complete', 'Download Complete.'
379+
)
380+
return
381+
# if we haven't returned, the user wants to upload
382+
try:
383+
sftp_model.upload_file(csvfile, destination_path)
384+
except Exception as e:
385+
messagebox.showerror('Error uploading', str(e))
386+
else:
387+
messagebox.showinfo(
388+
'Success',
389+
f'{csvfile} successfully uploaded to SFTP server.'
390+
)
391+
345392

346393
def _upload_to_corporate_rest(self, *_):
347-
csvfile = self._create_csv_extract()
348-
if csvfile is None:
394+
395+
# create csv file
396+
try:
397+
csvfile = self._create_csv_extract()
398+
except Exception as e:
349399
messagebox.showwarning(
350-
title='No records',
351-
message='There are no records to upload'
400+
title='Error', message=str(e)
352401
)
353402
return
403+
404+
# Authenticate to the rest server
354405
d = v.LoginDialog(
355406
self, 'Login to ABQ Corporate REST API'
356407
)
357408
if d.result is not None:
358409
username, password = d.result
359410
else:
360411
return
412+
413+
# create REST model
414+
rest_model = m.CorporateRestModel(
415+
self.settings['abq_rest_url'].get()
416+
)
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
361424
try:
362-
n.upload_to_corporate_rest(
363-
csvfile,
364-
self.settings['abq_upload_url'].get(),
365-
self.settings['abq_auth_url'].get(),
366-
username,
367-
password
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?'
368436
)
369-
except n.requests.ConnectionError as e:
370-
messagebox.showerror('Error connecting', str(e))
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+
try:
461+
rest_model.upload_file(csvfile)
371462
except Exception as e:
372-
messagebox.showerror('General Exception', str(e))
463+
messagebox.showerror('Error uploading', str(e))
373464
else:
374465
messagebox.showinfo(
375466
'Success',

Chapter13/ABQ_Data_Entry/abq_data_entry/mainmenu.py

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -67,25 +67,18 @@ def _add_weather_download(self, menu):
6767
menu.add_command(
6868
label="Update Weather Data",
6969
command=self._event('<<UpdateWeatherData>>'),
70-
accelerator=self.accelerators.get('weather'),
71-
image=self.icons.get('weather'),
72-
compound=tk.LEFT
7370
)
7471

7572
def _add_rest_upload(self, menu):
7673
menu.add_command(
7774
label="Upload CSV to corporate REST",
7875
command=self._event('<<UploadToCorporateREST>>'),
79-
image=self.icons.get('upload_rest'),
80-
compound=tk.LEFT
8176
)
8277

83-
def _add_ftp_upload(self, menu):
78+
def _add_sftp_upload(self, menu):
8479
menu.add_command(
85-
label="Upload CSV to corporate FTP",
86-
command=self._event('<<UploadToCorporateFTP>>'),
87-
image=self.icons.get('upload_ftp'),
88-
compound=tk.LEFT
80+
label="Upload CSV to corporate SFTP",
81+
command=self._event('<<UploadToCorporateSFTP>>'),
8982
)
9083

9184
def _add_autofill_date(self, menu):
@@ -157,7 +150,7 @@ def _build_menu(self):
157150
self._menus['Tools'] = tk.Menu(self, tearoff=False, **self.styles)
158151
self._add_weather_download(self._menus['Tools'])
159152
self._add_rest_upload(self._menus['Tools'])
160-
self._add_ftp_upload(self._menus['Tools'])
153+
self._add_sftp_upload(self._menus['Tools'])
161154

162155
# The options menu
163156
self._menus['Options'] = tk.Menu(self, tearoff=False, **self.styles)
@@ -265,7 +258,7 @@ def _build_menu(self):
265258
self._add_themes_menu(self._menus['Tools'])
266259
self._add_weather_download(self._menus['Tools'])
267260
self._add_rest_upload(self._menus['Tools'])
268-
self._add_ftp_upload(self._menus['Tools'])
261+
self._add_sftp_upload(self._menus['Tools'])
269262

270263
# The help menu
271264
self._menus['Help'] = tk.Menu(self, tearoff=False)
@@ -310,7 +303,7 @@ def _build_menu(self):
310303
self._menus['Tools'] = tk.Menu(self, tearoff=False, **self.styles)
311304
self._add_weather_download(self._menus['Tools'])
312305
self._add_rest_upload(self._menus['Tools'])
313-
self._add_ftp_upload(self._menus['Tools'])
306+
self._add_sftp_upload(self._menus['Tools'])
314307

315308
# The View menu
316309
self._menus['View'] = tk.Menu(self, tearoff=False, **self.styles)
@@ -379,7 +372,7 @@ def _build_menu(self):
379372
self._menus['Tools'] = tk.Menu(self, tearoff=False)
380373
self._add_weather_download(self._menus['Tools'])
381374
self._add_rest_upload(self._menus['Tools'])
382-
self._add_ftp_upload(self._menus['Tools'])
375+
self._add_sftp_upload(self._menus['Tools'])
383376

384377
# View menu
385378
self._menus['View'] = tk.Menu(self, tearoff=False)

0 commit comments

Comments
 (0)