Skip to content

Commit a28bb4c

Browse files
AppStore app: rewrite install/update to asyncio to eliminate thread
1 parent 382a366 commit a28bb4c

File tree

1 file changed

+45
-33
lines changed
  • internal_filesystem/builtin/apps/com.micropythonos.appstore/assets

1 file changed

+45
-33
lines changed

internal_filesystem/builtin/apps/com.micropythonos.appstore/assets/appstore.py

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -179,16 +179,39 @@ def show_app_detail(self, app):
179179
intent.putExtra("appstore", self)
180180
self.startActivity(intent)
181181

182-
async def download_url(self, url):
182+
async def download_url(self, url, outfile=None):
183183
print(f"Downloading {url}")
184184
#await TaskManager.sleep(4) # test slowness
185185
try:
186186
async with self.aiohttp_session.get(url) as response:
187-
if response.status >= 200 and response.status < 400:
187+
if response.status < 200 or response.status >= 400:
188+
return None
189+
if not outfile:
188190
return await response.read()
189-
print(f"Done downloading {url}")
191+
else:
192+
# Would be good to check free available space first
193+
chunk_size = 1024
194+
print("headers:") ; print(response.headers)
195+
total_size = response.headers.get('Content-Length') # some servers don't send this
196+
print(f"download_url writing to {outfile} of {total_size} bytes in chunks of size {chunk_size}")
197+
with open(outfile, 'wb') as fd:
198+
print("opened file...")
199+
print(dir(response.content))
200+
while True:
201+
#print("reading next chunk...")
202+
# Would be better to use wait_for() to handle timeouts:
203+
chunk = await response.content.read(chunk_size)
204+
#print(f"got chunk: {chunk}")
205+
if not chunk:
206+
break
207+
#print("writing chunk...")
208+
fd.write(chunk)
209+
#print("wrote chunk")
210+
print(f"Done downloading {url}")
211+
return True
190212
except Exception as e:
191213
print(f"download_url got exception {e}")
214+
return False
192215

193216
@staticmethod
194217
def badgehub_app_to_mpos_app(bhapp):
@@ -435,8 +458,7 @@ def toggle_install(self, app_obj):
435458
label_text = self.install_label.get_text()
436459
if label_text == self.action_label_install:
437460
try:
438-
_thread.stack_size(mpos.apps.good_stack_size())
439-
_thread.start_new_thread(self.download_and_install, (download_url, f"apps/{fullname}", fullname))
461+
TaskManager.create_task(self.download_and_install(download_url, f"apps/{fullname}", fullname))
440462
except Exception as e:
441463
print("Could not start download_and_install thread: ", e)
442464
elif label_text == self.action_label_uninstall or label_text == self.action_label_restore:
@@ -478,48 +500,38 @@ def uninstall_app(self, app_fullname):
478500
self.update_button.remove_flag(lv.obj.FLAG.HIDDEN)
479501
self.install_button.set_size(lv.pct(47), 40) # if a builtin app was removed, then it was overridden, and a new version is available, so make space for update button
480502

481-
def download_and_install(self, zip_url, dest_folder, app_fullname):
503+
async def download_and_install(self, zip_url, dest_folder, app_fullname):
482504
self.install_button.add_state(lv.STATE.DISABLED)
483505
self.install_label.set_text("Please wait...")
484506
self.progress_bar.remove_flag(lv.obj.FLAG.HIDDEN)
485507
self.progress_bar.set_value(20, True)
486-
time.sleep(1) # seems silly but otherwise it goes so quickly that the user can't tell something happened and gets confused
508+
TaskManager.sleep(1) # seems silly but otherwise it goes so quickly that the user can't tell something happened and gets confused
509+
# Download the .mpk file to temporary location
510+
try:
511+
os.remove(temp_zip_path)
512+
except Exception:
513+
pass
487514
try:
488-
# Step 1: Download the .mpk file
489-
print(f"Downloading .mpk file from: {zip_url}")
490-
response = requests.get(zip_url, timeout=10) # TODO: use stream=True and do it in chunks like in OSUpdate
491-
if response.status_code != 200:
492-
print("Download failed: Status code", response.status_code)
493-
response.close()
515+
os.mkdir("tmp")
516+
except Exception:
517+
pass
518+
self.progress_bar.set_value(40, True)
519+
temp_zip_path = "tmp/temp.mpk"
520+
print(f"Downloading .mpk file from: {zip_url} to {temp_zip_path}")
521+
try:
522+
result = await self.appstore.download_url(zip_url, outfile=temp_zip_path)
523+
if result is not True:
524+
print("Download failed...")
494525
self.set_install_label(app_fullname)
495-
self.progress_bar.set_value(40, True)
496-
# Save the .mpk file to a temporary location
497-
try:
498-
os.remove(temp_zip_path)
499-
except Exception:
500-
pass
501-
try:
502-
os.mkdir("tmp")
503-
except Exception:
504-
pass
505-
temp_zip_path = "tmp/temp.mpk"
506-
print(f"Writing to temporary mpk path: {temp_zip_path}")
507-
# TODO: check free available space first!
508-
with open(temp_zip_path, "wb") as f:
509-
f.write(response.content)
510526
self.progress_bar.set_value(60, True)
511-
response.close()
512527
print("Downloaded .mpk file, size:", os.stat(temp_zip_path)[6], "bytes")
513528
except Exception as e:
514529
print("Download failed:", str(e))
515530
# Would be good to show error message here if it fails...
516-
finally:
517-
if 'response' in locals():
518-
response.close()
519531
# Step 2: install it:
520532
PackageManager.install_mpk(temp_zip_path, dest_folder) # ERROR: temp_zip_path might not be set if download failed!
521533
# Success:
522-
time.sleep(1) # seems silly but otherwise it goes so quickly that the user can't tell something happened and gets confused
534+
TaskManager.sleep(1) # seems silly but otherwise it goes so quickly that the user can't tell something happened and gets confused
523535
self.progress_bar.set_value(100, False)
524536
self.progress_bar.add_flag(lv.obj.FLAG.HIDDEN)
525537
self.progress_bar.set_value(0, False)

0 commit comments

Comments
 (0)