@@ -312,95 +312,70 @@ def is_installed_by_name(app_fullname):
312312 return AppManager .is_installed_by_path (f"apps/{ app_fullname } " ) or AppManager .is_installed_by_path (f"builtin/apps/{ app_fullname } " )
313313
314314 @staticmethod
315- def execute_script (script_source , is_file , classname , cwd = None , app_fullname = None ):
316- """Run the script in the current thread . Returns True if successful."""
315+ def execute_script (script_source , classname , cwd = None , app_fullname = None ):
316+ """Run an app entrypoint file by importing its module . Returns True if successful."""
317317 import utime # for timing read and compile
318318 import mpos .ui
319319 import _thread
320320 import sys
321+
322+ def _start_activity (main_activity , source_name ):
323+ if main_activity :
324+ from mpos .activity_navigator import ActivityNavigator
325+ from .intent import Intent
326+
327+ start_time = utime .ticks_ms ()
328+ ActivityNavigator .startActivity (
329+ Intent (activity_class = main_activity , app_fullname = app_fullname )
330+ )
331+ end_time = utime .ticks_diff (utime .ticks_ms (), start_time )
332+ print (
333+ f"execute_script: ActivityNavigator.startActivity took { end_time } ms ({ source_name } )"
334+ )
335+ return True
336+ print (f"Warning: could not find app's main_activity { classname } " )
337+ return False
338+
321339 thread_id = _thread .get_ident ()
322- compile_name = 'script' if not is_file else script_source
340+ compile_name = script_source
323341 executed_name = compile_name
324342 print (f"Thread { thread_id } : executing script with cwd: { cwd } " )
325343 try :
326- script_globals = {
327- '__name__' : "__main__" , # in case the script wants this
328- '__file__' : compile_name # useful for logger
329- }
330344 print (f"Thread { thread_id } : starting script" )
331345 path_before = sys .path [:] # Make a copy, not a reference
332346 if cwd :
333- sys .path .append (cwd )
347+ if cwd in sys .path :
348+ sys .path .remove (cwd )
349+ sys .path .insert (0 , cwd )
334350 try :
335- if is_file and script_source .endswith (".py" ):
336- mpy_source = script_source [:- 3 ] + ".mpy"
337- try :
338- if os .stat (mpy_source )[0 ] & 0x8000 :
339- print (f"Thread { thread_id } : found precompiled script { mpy_source } " )
340- executed_name = mpy_source
341- module_name = mpy_source .rsplit ("/" , 1 )[- 1 ][:- 4 ]
342- import builtins
343- if module_name in sys .modules :
344- del sys .modules [module_name ]
345- try :
346- print (f"app_manager.py trying to __import__({ module_name } )" )
347- module = __import__ (module_name )
348- except Exception as e :
349- print (f"app_manager.py failed to __import__({ module_name } " )
350- module .__file__ = mpy_source
351- module .__name__ = "__main__"
352- main_activity = getattr (module , classname , None )
353- if main_activity :
354- from mpos .activity_navigator import ActivityNavigator
355- from .intent import Intent
356- start_time = utime .ticks_ms ()
357- ActivityNavigator .startActivity (Intent (activity_class = main_activity , app_fullname = app_fullname ))
358- end_time = utime .ticks_diff (utime .ticks_ms (), start_time )
359- print (f"execute_script: ActivityNavigator.startActivity took { end_time } ms" )
360- return True
361- raise Exception ("could not find app's main_activity {} in {}" .format (classname , mpy_source ))
362- except OSError :
363- pass
364- except Exception as e :
365- print (f"WARNING: failed running precompiled script { mpy_source } : { e } " )
366- sys .print_exception (e )
367-
368- if is_file :
369- print (f"Thread { thread_id } : reading script from file { script_source } " )
370- with open (script_source , 'r' ) as f : # No need to check if it exists as exceptions are caught
371- start_time = utime .ticks_ms ()
372- script_source = f .read ()
373- read_time = utime .ticks_diff (utime .ticks_ms (), start_time )
374- print (f"execute_script: reading script_source took { read_time } ms" )
375-
376- start_time = utime .ticks_ms ()
377- compiled_script = compile (script_source , compile_name , 'exec' )
378- compile_time = utime .ticks_diff (utime .ticks_ms (), start_time )
379- print (f"execute_script: compiling script_source took { compile_time } ms" )
380- start_time = utime .ticks_ms ()
381- exec (compiled_script , script_globals )
382- end_time = utime .ticks_diff (utime .ticks_ms (), start_time )
383- print (f"apps.py execute_script: exec took { end_time } ms" )
384- # Introspect globals
385- classes = {k : v for k , v in script_globals .items () if isinstance (v , type )}
386- functions = {k : v for k , v in script_globals .items () if callable (v ) and not isinstance (v , type )}
387- variables = {k : v for k , v in script_globals .items () if not callable (v )}
388- print ("Classes:" , classes .keys ()) # This lists a whole bunch of classes, including lib/mpos/ stuff
389- print ("Functions:" , functions .keys ())
390- print ("Variables:" , variables .keys ())
391- main_activity = script_globals .get (classname )
392- if main_activity :
393- from mpos .activity_navigator import ActivityNavigator
394- from .intent import Intent
351+ module_name = script_source .rsplit ("/" , 1 )[- 1 ]
352+ if "." in module_name :
353+ module_name = module_name .rsplit ("." , 1 )[0 ]
354+ previous_module = sys .modules .get (module_name , None )
355+ had_previous_module = module_name in sys .modules
356+ try :
357+ if had_previous_module :
358+ del sys .modules [module_name ]
395359 start_time = utime .ticks_ms ()
396- ActivityNavigator .startActivity (
397- Intent (activity_class = main_activity , app_fullname = app_fullname )
360+ module = __import__ (module_name )
361+ import_time = utime .ticks_diff (utime .ticks_ms (), start_time )
362+ executed_name = getattr (module , "__file__" , script_source )
363+ print (
364+ f"execute_script: importing module { module_name } took { import_time } ms"
398365 )
399- end_time = utime .ticks_diff (utime .ticks_ms (), start_time )
400- print (f"execute_script: ActivityNavigator.startActivity took { end_time } ms" )
401- else :
402- print (f"Warning: could not find app's main_activity { classname } " )
366+ return _start_activity (getattr (module , classname , None ), executed_name )
367+ except Exception as import_error :
368+ print (
369+ f"WARNING: failed importing app module { module_name } "
370+ f"from { compile_name } : { import_error } "
371+ )
372+ sys .print_exception (import_error )
403373 return False
374+ finally :
375+ if had_previous_module :
376+ sys .modules [module_name ] = previous_module
377+ elif module_name in sys .modules :
378+ del sys .modules [module_name ]
404379 except Exception as e :
405380 print (f"Thread { thread_id } : exception during execution:" )
406381 sys .print_exception (e )
@@ -409,7 +384,6 @@ def execute_script(script_source, is_file, classname, cwd=None, app_fullname=Non
409384 # Always restore sys.path, even if we return early or raise an exception
410385 print (f"Thread { thread_id } : script { executed_name } finished, restoring sys.path from { sys .path } to { path_before } " )
411386 sys .path = path_before
412- return True
413387 except Exception as e :
414388 print (f"Thread { thread_id } : error:" )
415389 import sys
@@ -437,7 +411,6 @@ def start_app(fullname):
437411 classname = app .main_launcher_activity .get ("classname" )
438412 result = AppManager .execute_script (
439413 app .installed_path + "/" + entrypoint ,
440- True ,
441414 classname ,
442415 app .installed_path + "/assets/" ,
443416 app_fullname = fullname ,
0 commit comments