Skip to content

Commit cfab3b7

Browse files
committed
Changes per chapter 14 rewrite
1 parent f400417 commit cfab3b7

File tree

9 files changed

+546
-1563
lines changed

9 files changed

+546
-1563
lines changed

Chapter14/ABQ_Data_Entry/abq_data_entry/application.py

Lines changed: 137 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)