=== modified file 'fetch_image_ui.py'
@@ -31,6 +31,8 @@
import unittest
import operator
import Queue
+import time
+import datetime
def add_button(bind_to,
@@ -43,9 +45,9 @@
"""Create a radio button with event bindings."""
if(style != None):
- radio_button = wx.RadioButton(bind_to, label = label, style = style)
+ radio_button = wx.RadioButton(bind_to, label=label, style=style)
else:
- radio_button = wx.RadioButton(bind_to, label = label)
+ radio_button = wx.RadioButton(bind_to, label=label)
sizer.Add(radio_button, 0, wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP, 5)
bind_to.Bind(wx.EVT_RADIOBUTTON, select_event, radio_button)
@@ -126,9 +128,9 @@
self.box2 = wx.BoxSizer(wx.VERTICAL)
header = wx.StaticText(self,
- label = "Please select the hardware that you "
- "would like to build an image for from "
- "the following list")
+ label="Please select the hardware that you "
+ "would like to build an image for from "
+ "the following list")
header.Wrap(width - 10) # -10 because boarder below is 5 pixels wide
@@ -143,11 +145,12 @@
self.settings['hardware'] = default_hardware
self.settings['compatable_hwpacks'] = (
self.settings['choice']['hwpack'][self.settings['hardware']])
-
+
self.cb_hardware = wx.ComboBox(self,
- value =
- self.settings['choice']['hardware'][default_hardware],
- style = wx.CB_DROPDOWN | wx.CB_READONLY)
+ value=self.settings['choice']
+ ['hardware']
+ [default_hardware],
+ style=wx.CB_DROPDOWN | wx.CB_READONLY)
self.Bind(wx.EVT_COMBOBOX,
self.event_combo_box_hardware,
@@ -201,8 +204,8 @@
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.wizard = parent
- header = wx.StaticText(self, label = "Please select the stable Linaro "
- "release you would like to use")
+ header = wx.StaticText(self, label="Please select the stable Linaro "
+ "release you would like to use")
header.Wrap(width - 10) # -10 because boarder below is 5 pixels wide
@@ -215,8 +218,8 @@
default_release = self.settings['UI']['translate'][platforms[-1]]
self.cb_release = wx.ComboBox(self,
- value = default_release,
- style = wx.CB_DROPDOWN | wx.CB_READONLY)
+ value=default_release,
+ style=wx.CB_DROPDOWN | wx.CB_READONLY)
self.Bind(wx.EVT_COMBOBOX,
self.event_combo_box_release,
self.cb_release)
@@ -234,12 +237,12 @@
self.cb_release.Append(item, item.upper())
self.cb_build = wx.ComboBox(self,
- style = wx.CB_DROPDOWN | wx.CB_READONLY)
+ style=wx.CB_DROPDOWN | wx.CB_READONLY)
self.Bind(wx.EVT_COMBOBOX, self.event_combo_box_build, self.cb_build)
self.box1.Add(self.cb_release, 0,
wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP, 5)
- self.box1.Add(self.cb_build, 0,
+ self.box1.Add(self.cb_build, 0,
wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP, 5)
self.sizer.Add(self.box1, 0, wx.ALIGN_LEFT | wx.ALL, 5)
self.SetSizerAndFit(self.sizer)
@@ -255,7 +258,7 @@
self.cb_build.SetValue("No build available")
for build in builds:
- if( self.db.hardware_is_available_for_platform_build(
+ if(self.db.hardware_is_available_for_platform_build(
self.settings['compatable_hwpacks'],
self.settings['platform'],
build)
@@ -336,12 +339,12 @@
self.sizer = wx.BoxSizer(wx.VERTICAL)
header = wx.StaticText(self,
- label = "Builds are created most days. First "
- "please select the day on which the "
- "build you would like to use was built,"
- " then, if there was more than one "
- "build that day you will be able to "
- "select the build number.")
+ label="Builds are created most days. First "
+ "please select the day on which the "
+ "build you would like to use was built,"
+ " then, if there was more than one "
+ "build that day you will be able to "
+ "select the build number.")
header.Wrap(width - 10) # -10 because boarder below is 5 pixels wide
box1 = wx.BoxSizer(wx.VERTICAL)
@@ -353,8 +356,8 @@
self.today.SetToCurrent()
self.settings['build_date'] = self.today.FormatISODate().encode('ascii')
- dpc = wx.DatePickerCtrl(self, size = (120, -1),
- style = wx.DP_DEFAULT)
+ dpc = wx.DatePickerCtrl(self, size=(120, -1),
+ style=wx.DP_DEFAULT)
self.Bind(wx.EVT_DATE_CHANGED, self.on_date_changed, dpc)
#--- Build number Combo Box ---
@@ -363,7 +366,7 @@
self.settings['build_number'] = 0
self.update_build()
self.cb_build = wx.ComboBox(self,
- style = wx.CB_DROPDOWN | wx.CB_READONLY)
+ style=wx.CB_DROPDOWN | wx.CB_READONLY)
self.Bind(wx.EVT_COMBOBOX, self.event_combo_box_build, self.cb_build)
#--- Layout ---
@@ -493,16 +496,16 @@
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.settings['image'] = None
- header = wx.StaticText(self, label = "Please select the operating "
- "system you would like to run on "
- "your hardware.")
+ header = wx.StaticText(self, label="Please select the operating "
+ "system you would like to run on "
+ "your hardware.")
header.Wrap(width - 10) # -10 because boarder below is 5 pixels wide
self.box1 = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(header)
self.cb_image = wx.ComboBox(self,
- style = wx.CB_DROPDOWN | wx.CB_READONLY)
+ style=wx.CB_DROPDOWN | wx.CB_READONLY)
self.Bind(wx.EVT_COMBOBOX, self.event_combo_box_os, self.cb_image)
#--- Layout ---
@@ -679,7 +682,7 @@
self.settings['path_selected'] = ""
header = wx.StaticText(self,
- label = "Media Creation Settings\n\n"
+ label="Media Creation Settings\n\n"
"Please select if you would like to write the "
"file system I am about to create to a memory "
"card, or to a file on the local file system.")
@@ -691,8 +694,8 @@
default_target = file_systems[0]
self.settings['rootfs'] = default_target
cb_rootfs = wx.ComboBox(self,
- value = default_target,
- style = wx.CB_DROPDOWN | wx.CB_READONLY)
+ value=default_target,
+ style=wx.CB_DROPDOWN | wx.CB_READONLY)
for item in file_systems:
cb_rootfs.Append(item, item.upper())
@@ -737,14 +740,14 @@
self.help_text_values = {"device": "Please select a device to write "
"the file system to:",
+
"file": "Please select a file to write the "
"file system to:"}
self.help_text = wx.StaticText(
self,
- label =
- self.help_text_values[
- self.settings['write_to_file_or_device']])
+ label=self.help_text_values[
+ self.settings['write_to_file_or_device']])
self.help_text.Wrap(width - 10)
#-- File/dev picker --
@@ -774,7 +777,7 @@
#-- Combo boxes for hardware and image selection --
optional_settings_box_title = wx.StaticBox(
self,
- label = " Optional Settings ")
+ label=" Optional Settings ")
self.optional_settings_box = wx.StaticBoxSizer(
optional_settings_box_title,
@@ -790,7 +793,7 @@
grid1.Add(cb_rootfs, 0, wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP, 5)
grid1.Add(wx.StaticText(self,
- label = "The root file system of the image"),
+ label="The root file system of the image"),
0,
wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
5)
@@ -811,14 +814,14 @@
# Add a choice of MB or GB for size input
units = ["GB", "MB"]
self.size_unit = units[0] # Set the default unit
- unit_choice = wx.Choice(self, -1, (100, 50), choices = units)
+ unit_choice = wx.Choice(self, -1, (100, 50), choices=units)
self.Bind(wx.EVT_CHOICE, self.event_chose_unit, unit_choice)
file_size_grid.Add(unit_choice, 0, wx.ALIGN_RIGHT | wx.TOP, 5)
# Back out of the extra grid, add some help text
grid1.Add(wx.StaticText(
self,
- label = "Writing to file only: Image file size"),
+ label="Writing to file only: Image file size"),
0,
wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
5)
@@ -829,15 +832,15 @@
wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
5)
- grid1.Add(wx.StaticText(self, label = "Swap file size in MB"),
+ grid1.Add(wx.StaticText(self, label="Swap file size in MB"),
0,
wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
5)
self.cb_hwpacks = wx.ComboBox(
self,
- value = self.settings['compatable_hwpacks'][0],
- style = wx.CB_DROPDOWN | wx.CB_READONLY)
+ value=self.settings['compatable_hwpacks'][0],
+ style=wx.CB_DROPDOWN | wx.CB_READONLY)
self.Bind(wx.EVT_COMBOBOX,
self.event_combo_box_hwpack,
@@ -848,14 +851,14 @@
wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
5)
- grid1.Add(wx.StaticText(self, label = "Compatible hardware packs"),
+ grid1.Add(wx.StaticText(self, label="Compatible hardware packs"),
0,
wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
5)
self.optional_settings_box.Add(grid1, 0, wx.ALIGN_LEFT | wx.ALL, 5)
- confirm_mmc_usage_title = wx.StaticBox(self, label = " Are you sure? ")
+ confirm_mmc_usage_title = wx.StaticBox(self, label=" Are you sure? ")
self.confirm_mmc_usage_box = wx.StaticBoxSizer(confirm_mmc_usage_title,
wx.VERTICAL)
@@ -1031,7 +1034,7 @@
self.width = width
self.wizard = parent
- header = wx.StaticText(self, label = """Installing...""")
+ header = wx.StaticText(self, label="""Installing...""")
header.Wrap(width - 10) # -10 because boarder below is 5 pixels wide
self.sizer.Add(header)
@@ -1039,7 +1042,7 @@
# We expect to print 4 lines of information, reserve space using blank
# lines.
- self.settings_summary_text = wx.StaticText(self, label = "\n\n\n\n")
+ self.settings_summary_text = wx.StaticText(self, label="\n\n\n\n")
self.settings_summary_text.Wrap(width - 10)
self.box1.Add(self.settings_summary_text, 0, wx.ALIGN_LEFT | wx.ALL, 5)
@@ -1053,7 +1056,12 @@
self.start_button.SetSize(self.start_button.GetBestSize())
self.box1.Add(self.start_button, 0, wx.ALIGN_LEFT | wx.ALL, 5)
- self.status_grid = wx.FlexGridSizer(0, 2, 0, 0)
+ self.download_guage = wx.Gauge(self,
+ -1,
+ 1000,
+ size=(self.width * 2 / 3, 25))
+
+ self.status_grid = wx.FlexGridSizer(0, 2)
self.status_grid.Add(wx.StaticText(self, label="Downloading files"),
0,
@@ -1061,11 +1069,24 @@
5)
self.downloading_files_status = wx.StaticText(self, label="")
+
self.status_grid.Add(self.downloading_files_status,
0,
wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
5)
+ self.status_grid.Add(self.download_guage,
+ 0,
+ wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
+ 5)
+
+ self.downloading_files_info = wx.StaticText(self, label="")
+
+ self.status_grid.Add(self.downloading_files_info,
+ 0,
+ wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
+ 5)
+
self.status_grid.Add(wx.StaticText(self, label="Unpacking downloads"),
0,
wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
@@ -1147,7 +1168,7 @@
settings_summary += ( "Writing image to "
+ self.settings['write_to_file_or_device']
- + " "
+ + " "
+ path)
self.settings_summary_text.SetLabel(settings_summary)
@@ -1175,29 +1196,26 @@
if(image_url and hwpack_url):
- print image_url
- print hwpack_url
-
self.file_handler = FetchImage.FileHandler()
+ self.timer = wx.Timer(self)
+ self.Bind(wx.EVT_TIMER, self.timer_ping, self.timer)
+ self.timer.Start(milliseconds=100, oneShot=True)
+
tools_dir = os.path.dirname(__file__)
if tools_dir == '':
tools_dir = None
- self.file_handler.create_media(image_url,
- hwpack_url,
- self.settings,
- tools_dir,
- True,
- self)
-
- self.timer = wx.Timer(self)
- self.Bind(wx.EVT_TIMER, self.timer_ping, self.timer)
- self.timer.Start(milliseconds=100, oneShot=True)
-
self.start_button.Disable()
self.event_queue = Queue.Queue()
- self.file_handler.start_lmc_gui_thread(self.event_queue)
+ self.lmc_thread = self.file_handler.LinaroMediaCreate(
+ image_url,
+ hwpack_url,
+ self.file_handler,
+ self.event_queue,
+ self.settings,
+ tools_dir)
+ self.lmc_thread.start()
else:
print >> sys.stderr, ("Unable to find files that match the"
"parameters specified")
@@ -1207,27 +1225,28 @@
linaro-media-create every 100ms. This is the function which is called
to do that polling."""
- if self.event_queue.empty() == False:
+ while not self.event_queue.empty():
event = self.event_queue.get()
if event[0] == "start":
self.event_start(event[1])
- self.timer.Start(milliseconds=100, oneShot=True)
elif event[0] == "end":
self.event_end(event[1])
- self.timer.Start(milliseconds=100, oneShot=True)
elif event == "terminate":
# Process complete. Enable next button.
self.wizard.FindWindowById(wx.ID_FORWARD).Enable()
self.populate_file_system_status.SetLabel("Done")
+ return # Even if queue isn't empty, stop processing it
+
+ elif event[0] == "update":
+ self.event_update(event[1], event[2], event[3])
else:
print >> sys.stderr, "timer_ping: Unhandled event", event
- else:
- self.timer.Start(milliseconds=100, oneShot=True)
+ self.timer.Start(milliseconds=50, oneShot=True)
def unsigned_packages_query(self, package_list):
message = ('In order to continue, I need to install some unsigned'
@@ -1264,7 +1283,7 @@
self.file_handler.kill_create_media()
sys.exit(1)
else:
- self.file_handler.send_to_create_process("y")
+ self.lmc_thread.send_to_create_process("y")
elif event == "create file system":
self.create_file_system_status.SetLabel("Running")
@@ -1289,6 +1308,79 @@
else:
print "Unhhandled end event:", event
+ def event_update(self, task, update_type, value):
+ if task == "download":
+ if update_type == "name":
+ self.downloading_files_status.SetLabel("Downloading")
+ self.old_time = time.time()
+ self.old_bytes_downloaded = 0
+
+ elif update_type == "progress":
+ self.total_bytes_downloaded += value
+
+ time_difference = time.time() - self.old_time
+
+ if time_difference > 1.0:
+ self.old_time = time.time()
+
+ # More than a second has passed since we calculated data
+ # rate
+ speed = ( float( self.total_bytes_downloaded
+ - self.old_bytes_downloaded)
+ / time_difference)
+
+ self.old_bytes_downloaded = self.total_bytes_downloaded
+
+ self.speeds.append(speed)
+
+ average_speed = 0
+ speeds_accumulated = 0
+ for speed in reversed(self.speeds):
+ average_speed += speed
+ speeds_accumulated += 1
+
+ if speeds_accumulated == 6:
+ break # do rolling average of 6 seconds
+
+ average_speed /= speeds_accumulated
+
+ time_remaining = ( ( self.total_bytes_to_download
+ - self.total_bytes_downloaded)
+ / speed)
+
+ pretty_time = str(datetime.timedelta(seconds=int(
+ time_remaining)))
+
+ # Following table assumes we don't get past TBps internet
+ # connections soon :-)
+ units = ["Bps", "kBps", "MBps", "GBps", "TBps"]
+ units_index = 0
+ while speed > 1024:
+ speed /= 1024
+ units_index += 1
+
+ info = "Downloading at {0:.1f} {1}".format(
+ speed,
+ units[units_index])
+
+ self.downloading_files_status.SetLabel(info)
+
+ info = "{0} remaining".format(
+ pretty_time)
+
+ self.downloading_files_info.SetLabel(info)
+
+ self.download_guage.SetValue( 1000
+ * self.total_bytes_downloaded
+ / self.total_bytes_to_download)
+
+ elif update_type == "total bytes":
+ self.total_bytes_to_download = value
+ self.total_bytes_downloaded = 0
+ self.speeds = [] # keep an array of speeds used to calculate
+ # the estimated time remaining - by not just using the
+ # current speed we can stop the ETA bouncing around too much.
+
def event_combo_box_release(self, evt):
pass
@@ -1371,14 +1463,14 @@
else: # Always enable the forward button if reversing into a page
self.wizard.FindWindowById(wx.ID_FORWARD).Enable()
- def go(self, first_page):
+ def go(self):
file_handler = FetchImage.FileHandler()
self.config = FetchImage.FetchImageConfig()
self.config.settings["force_download"] = False
self.config.settings['compatable_hwpacks'] = ['foo']
# If the settings file and server index need updating, grab them
- file_handler.update_files_from_server(show_wx_progress = True)
+ file_handler.update_files_from_server()
# Load settings YAML, which defines the parameters we ask for and
# acceptable responses from the user
@@ -1446,20 +1538,22 @@
self.wizard.RunWizard(self.pages['release_or_snapshot'])
-def run(start_page = None):
+def run():
"""Wrapper around the full wizard. Is encapsulated in its own function to
allow a restart to be performed, as described in __main___, easily"""
app = wx.PySimpleApp() # Start the application
- #logging.basicConfig(level=logging.INFO)
+ if app:
+ pass # We don't use this directly. Stop pyflakes complaining!
+
w = TestDriveWizard('Simple Wizard')
- return w.go(start_page)
+ return w.go()
class TestURLLookupFunctions(unittest.TestCase):
def setUp(self):
self.file_handler = FetchImage.FileHandler()
- self.file_handler.update_files_from_server(show_wx_progress = True)
+ self.file_handler.update_files_from_server()
self.config = FetchImage.FetchImageConfig()
self.config.settings["force_download"] = False
=== modified file 'linaro_image_tools/FetchImage.py'
@@ -52,15 +52,6 @@
"image-tools",
"fetch_image")
- class DummyEventHandler():
- """Just a sink for events if no event handler is provided to
- create_media"""
- def event_start(self, event):
- pass
-
- def event_end(self, event):
- pass
-
def has_key_and_evaluates_True(self, dictionary, key):
return bool(key in dictionary and dictionary[key])
@@ -72,17 +63,15 @@
list.append(setting_name)
list.append(dictionary[key])
- def create_media(self, image_url, hwpack_url, settings, tools_dir,
- run_in_gui=False, event_handler=None):
- """Create a command line for linaro-media-create based on the settings
- provided then run linaro-media-create, either in a separate thread
- (GUI mode) or in the current one (CLI mode)."""
+ def build_lmc_command(self,
+ binary_file,
+ hwpack_file,
+ settings,
+ tools_dir,
+ run_in_gui=False):
import linaro_image_tools.utils
- if event_handler == None:
- event_handler = self.DummyEventHandler()
-
args = []
args.append("pkexec")
@@ -100,41 +89,6 @@
if run_in_gui:
args.append("--nocheck-mmc")
- event_handler.event_start("download OS")
- try:
- binary_file = self.download(image_url,
- settings["force_download"],
- show_wx_progress=run_in_gui,
- wx_progress_title=
- "Downloading file 1 of 2")
- except Exception:
- # Download error. Hardly matters what, we can't continue.
- print "Unexpected error:", sys.exc_info()[0]
- logging.error("Unable to download " + image_url + " - aborting.")
- event_handler.event_end("download OS")
-
- if binary_file == None: # User hit cancel when downloading
- sys.exit(0)
-
- event_handler.event_start("download hwpack")
- try:
- hwpack_file = self.download(hwpack_url,
- settings["force_download"],
- show_wx_progress=run_in_gui,
- wx_progress_title=
- "Downloading file 2 of 2")
- except Exception:
- # Download error. Hardly matters what, we can't continue.
- print "Unexpected error:", sys.exc_info()[0]
- logging.error("Unable to download " + hwpack_url + " - aborting.")
- event_handler.event_end("download hwpack")
-
- if hwpack_file == None: # User hit cancel when downloading
- sys.exit(0)
-
- logging.info("Have downloaded OS binary to", binary_file,
- "and hardware pack to", hwpack_file)
-
if 'rootfs' in settings and settings['rootfs']:
args.append("--rootfs")
args.append(settings['rootfs'])
@@ -157,34 +111,74 @@
args.append("--hwpack")
args.append(hwpack_file)
- logging.info(args)
-
- if run_in_gui:
- self.lmcargs = args
- self.event_handler = event_handler
- self.started_lmc = False
- return
-
- else:
- self.create_process = subprocess.Popen(args)
- self.create_process.wait()
+ logging.info(" ".join(args))
+
+ return args
+
+ def create_media(self, image_url, hwpack_url, settings, tools_dir):
+ """Create a command line for linaro-media-create based on the settings
+ provided then run linaro-media-create, either in a separate thread
+ (GUI mode) or in the current one (CLI mode)."""
+
+ to_download = [(image_url, "OS"),
+ (hwpack_url, "hwpack")]
+ downloaded_files = self.download_files(to_download,
+ settings)
+
+ args = self.build_lmc_command(downloaded_files['OS'],
+ downloaded_files['hwpack'],
+ settings,
+ tools_dir)
+
+ self.create_process = subprocess.Popen(args)
+ self.create_process.wait()
class LinaroMediaCreate(threading.Thread):
"""Thread class for running linaro-media-create"""
- def __init__(self, event_handler, lmcargs, event_queue):
+ def __init__(self,
+ image_url,
+ hwpack_url,
+ file_handler,
+ event_queue,
+ settings,
+ tools_dir):
+
threading.Thread.__init__(self)
- self.event_handler = event_handler
- self.lmcargs = lmcargs
- self.event_queue = event_queue
+
+ self.image_url = image_url
+ self.hwpack_url = hwpack_url
+ self.file_handler = file_handler
+ self.event_queue = event_queue
+ self.settings = settings
+ self.tools_dir = tools_dir
def run(self):
- """Start linaro-media-create and look for lines in the output that:
- 1. Tell us that an event has happened that we can use to update the
- UI progress.
- 2. Tell us that linaro-media-create is asking a question that needs
- to be re-directed to the GUI"""
-
- self.create_process = subprocess.Popen(self.lmcargs,
+ """
+ 1. Download required files.
+ 2. Build linaro-media-create command
+ 3. Start linaro-media-create and look for lines in the output that:
+ 1. Tell us that an event has happened that we can use to update
+ the UI progress.
+ 2. Tell us that linaro-media-create is asking a question that
+ needs to be re-directed to the GUI
+ """
+
+ to_download = [(self.image_url, "OS"),
+ (self.hwpack_url, "hwpack")]
+
+ downloaded_files = self.file_handler.download_files(
+ to_download,
+ self.settings,
+ self.event_queue)
+
+ lmc_command = self.file_handler.build_lmc_command(
+ downloaded_files['OS'],
+ downloaded_files['hwpack'],
+ self.settings,
+ self.tools_dir,
+ True)
+
+ self.create_process = subprocess.Popen(lmc_command,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
@@ -262,18 +256,6 @@
print >> self.create_process.stdin, text
self.waiting_for_event_response = False
- def start_lmc_gui_thread(self, event_queue):
- self.lmc_thread = self.LinaroMediaCreate(self.event_handler,
- self.lmcargs, event_queue)
- self.lmc_thread.start()
-
- def kill_create_media(self):
- pass # TODO: Something!
- # Need to make sure all child processes are terminated.
-
- def send_to_create_process(self, text):
- self.lmc_thread.send_to_create_process(text)
-
def name_and_path_from_url(self, url):
"""Return the file name and the path at which the file will be stored
on the local system based on the URL we are downloading from"""
@@ -290,34 +272,94 @@
return file_name, file_path
- def create_wx_progress(self, title, message):
- """Create a standard WX progrss dialog"""
- import wx
- self.dlg = wx.ProgressDialog(title,
- message,
- maximum=1000,
- parent=None,
- style=wx.PD_CAN_ABORT
- | wx.PD_APP_MODAL
- | wx.PD_ELAPSED_TIME
- | wx.PD_AUTO_HIDE
- | wx.PD_REMAINING_TIME)
-
- def timer_ping(self):
- self.update_wx_process(self.download_count)
-
- def update_wx_progress(self, count):
- self.download_count = count
- (self.do_download, skip) = self.dlg.Update(count)
-
- def download(self, url, force_download=False,
- show_wx_progress=False, wx_progress_title=None):
+ def urllib2_open(self, url):
+ maxtries = 10
+ for trycount in range(0, maxtries):
+ try:
+ response = urllib2.urlopen(url)
+ except:
+ if trycount < maxtries - 1:
+ print "Unable to connect to", url, "retrying in 5 seconds..."
+ time.sleep(5)
+ continue
+ else:
+ print "Connect failed:", url
+ raise
+ return None
+ else:
+ return response
+
+ return None
+
+ def download_files(self,
+ downloads_list,
+ settings,
+ event_queue=None):
+ """
+ Download files specified in the downloads_list, which is a list of
+ url, name tuples.
+ """
+
+ downloaded_files = {}
+
+ bytes_to_download = 0
+
+ for url, name in downloads_list:
+ file_name, file_path = self.name_and_path_from_url(url)
+
+ file_name = file_path + os.sep + file_name
+ if os.path.exists(file_name):
+ continue # If file already exists, don't download it
+
+ response = self.urllib2_open(url)
+ if response:
+ bytes_to_download += int(response.info()
+ .getheader('Content-Length').strip())
+ response.close()
+
+ if event_queue:
+ event_queue.put(("update",
+ "download",
+ "total bytes",
+ bytes_to_download))
+
+ for url, name in downloads_list:
+ if event_queue:
+ event_queue.put(("start", "download " + name))
+ event_queue.put(("update",
+ "download",
+ "name",
+ name))
+
+ path = None
+ try:
+ path = self.download(url,
+ event_queue,
+ settings["force_download"])
+ except Exception:
+ # Download error. Hardly matters what, we can't continue.
+ print "Unexpected error:", sys.exc_info()[0]
+ logging.error("Unable to download " + url + " - aborting.")
+
+ if event_queue:
+ event_queue.put(("end", "download " + name))
+
+ if path == None: # User hit cancel when downloading
+ sys.exit(0)
+
+ downloaded_files[name] = path
+ logging.info("Have downloaded {0} to {1}".format(name, path))
+
+ return downloaded_files
+
+ def download(self,
+ url,
+ event_queue,
+ force_download=False):
"""Downloads the file requested buy URL to the local cache and returns
the full path to the downloaded file"""
file_name, file_path = self.name_and_path_from_url(url)
-
- just_file_name = file_name
file_name = file_path + os.sep + file_name
if not os.path.isdir(file_path):
@@ -328,23 +370,9 @@
"--force-download to override).")
return file_name
- logging.info("Fetching", url)
+ logging.info("Fetching " + url)
- maxtries = 10
- for trycount in range(0, maxtries):
- try:
- response = urllib2.urlopen(url)
- except:
- if trycount < maxtries - 1:
- print "Unable to download", url, "retrying in 5 seconds..."
- time.sleep(5)
- continue
- else:
- print "Download failed for some reason:", url
- raise
- return
- else:
- break
+ response = self.urllib2_open(url)
self.do_download = True
file_out = open(file_name, 'w')
@@ -356,28 +384,22 @@
if show_progress:
chunk_size = download_size_in_bytes / 1000
- if show_wx_progress:
- if wx_progress_title == None:
- wx_progress_title = "Downloading File"
- self.create_wx_progress(wx_progress_title,
- "Downloading " + just_file_name)
- else:
+ if not event_queue:
print "Fetching", url
else:
chunk_size = download_size_in_bytes
- if show_progress and show_wx_progress:
- # Just update the download box before we get the first %
- self.update_wx_progress(0)
-
printed_progress = False
while self.do_download:
chunk = response.read(chunk_size)
if len(chunk):
# Print a % download complete so we don't get too bored
if show_progress:
- if show_wx_progress:
- self.update_wx_progress(chunks_downloaded)
+ if event_queue:
+ event_queue.put(("update",
+ "download",
+ "progress",
+ len(chunk)))
else:
# Have 1000 chunks so div by 10 to get %...
sys.stdout.write("\r%d%%" % (chunks_downloaded / 10))
@@ -400,7 +422,7 @@
return file_name
- def download_if_old(self, url, force_download, show_wx_progress=False):
+ def download_if_old(self, url, event_queue, force_download):
file_name, file_path = self.name_and_path_from_url(url)
file_path_and_name = file_path + os.sep + file_name
@@ -411,25 +433,25 @@
force_download = (force_download == True
or ( time.mktime(time.localtime())
- os.path.getmtime(file_path_and_name)
- > 60 * 60 * 24))
+ > 60 * 60))
except OSError:
force_download = True # File not found...
- return self.download(url, force_download, show_wx_progress)
+ return self.download(url, event_queue, force_download)
def update_files_from_server(self, force_download=False,
- show_wx_progress=False):
+ event_queue=None):
- settings_url = "http://z.nanosheep.org/fetch_image_settings.yaml"
- server_index_url = "http://z.nanosheep.org/server_index.bz2"
+ settings_url = "http://releases.linaro.org/fetch_image/fetch_image_settings.yaml"
+ server_index_url = "http://releases.linaro.org/fetch_image/server_index.bz2"
self.settings_file = self.download_if_old(settings_url,
- force_download,
- show_wx_progress)
+ event_queue,
+ force_download)
self.index_file = self.download_if_old(server_index_url,
- force_download,
- show_wx_progress)
+ event_queue,
+ force_download)
zip_search = re.search(r"^(.*)\.bz2$", self.index_file)
@@ -484,9 +506,9 @@
self.settings['UI']['reverse-translate'][value] = key
def parse_args(self, args):
- parser = argparse.ArgumentParser(description=
- "Create a board image, first "
- "downloading any required files.")
+ parser = argparse.ArgumentParser(description="Create a board image, "
+ "first downloading any required "
+ "files.")
for (key, value) in self.settings['choice'].items():
parser.add_argument(
@@ -983,7 +1005,7 @@
loop_date_increment = -one_day
test_date[in_the] = current_date
-
+
while test_date[in_the] <= max_search_date:
test_date[in_the] += loop_date_increment