You've already forked MicroPythonOS
mirror of
https://github.com/m5stack/MicroPythonOS.git
synced 2026-05-20 11:51:27 -07:00
Move mpos.apps functionality to PackageManager
This commit is contained in:
@@ -9,7 +9,6 @@
|
||||
# All icons took: 1250ms
|
||||
# Most of this time is actually spent reading and parsing manifests.
|
||||
import lvgl as lv
|
||||
import mpos.apps
|
||||
from mpos import AppearanceManager, PackageManager, Activity, DisplayMetrics
|
||||
import time
|
||||
import uhashlib
|
||||
@@ -129,7 +128,7 @@ class Launcher(Activity):
|
||||
|
||||
# ----- events --------------------------------------------------
|
||||
app_cont.add_event_cb(
|
||||
lambda e, fullname=app.fullname: mpos.apps.start_app(fullname),
|
||||
lambda e, fullname=app.fullname: PackageManager.start_app(fullname),
|
||||
lv.EVENT.CLICKED, None)
|
||||
app_cont.add_event_cb(
|
||||
lambda e, cont=app_cont: self.focus_app_cont(cont),
|
||||
|
||||
@@ -46,7 +46,6 @@ from .ui.widget_animator import WidgetAnimator
|
||||
from .ui import focus_direction
|
||||
|
||||
# Utility modules
|
||||
from . import apps
|
||||
from . import bootloader
|
||||
from . import ui
|
||||
from . import config
|
||||
@@ -91,7 +90,7 @@ __all__ = [
|
||||
"click_button", "click_label", "click_keyboard_button", "find_button_with_text",
|
||||
"get_all_widgets_with_text",
|
||||
# Submodules
|
||||
"apps", "ui", "config", "net", "content", "time", "sensor_manager",
|
||||
"ui", "config", "net", "content", "time", "sensor_manager",
|
||||
"camera_manager", "sdcard", "battery_voltage", "audio", "hardware", "bootloader",
|
||||
# Timezone utilities
|
||||
"TimeZone"
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
import lvgl as lv
|
||||
|
||||
import _thread
|
||||
import traceback
|
||||
|
||||
import mpos.ui
|
||||
|
||||
# Run the script in the current thread:
|
||||
# Returns True if successful
|
||||
def execute_script(script_source, is_file, classname, cwd=None):
|
||||
import utime # for timing read and compile
|
||||
thread_id = _thread.get_ident()
|
||||
compile_name = 'script' if not is_file else script_source
|
||||
print(f"Thread {thread_id}: executing script with cwd: {cwd}")
|
||||
try:
|
||||
if is_file:
|
||||
print(f"Thread {thread_id}: reading script from file {script_source}")
|
||||
with open(script_source, 'r') as f: # No need to check if it exists as exceptions are caught
|
||||
start_time = utime.ticks_ms()
|
||||
script_source = f.read()
|
||||
read_time = utime.ticks_diff(utime.ticks_ms(), start_time)
|
||||
print(f"execute_script: reading script_source took {read_time}ms")
|
||||
script_globals = {
|
||||
'lv': lv,
|
||||
'__name__': "__main__"
|
||||
}
|
||||
print(f"Thread {thread_id}: starting script")
|
||||
import sys
|
||||
path_before = sys.path[:] # Make a copy, not a reference
|
||||
if cwd:
|
||||
sys.path.append(cwd)
|
||||
try:
|
||||
start_time = utime.ticks_ms()
|
||||
compiled_script = compile(script_source, compile_name, 'exec')
|
||||
compile_time = utime.ticks_diff(utime.ticks_ms(), start_time)
|
||||
print(f"execute_script: compiling script_source took {compile_time}ms")
|
||||
start_time = utime.ticks_ms()
|
||||
exec(compiled_script, script_globals)
|
||||
end_time = utime.ticks_diff(utime.ticks_ms(), start_time)
|
||||
print(f"apps.py execute_script: exec took {end_time}ms")
|
||||
# Introspect globals
|
||||
classes = {k: v for k, v in script_globals.items() if isinstance(v, type)}
|
||||
functions = {k: v for k, v in script_globals.items() if callable(v) and not isinstance(v, type)}
|
||||
variables = {k: v for k, v in script_globals.items() if not callable(v)}
|
||||
print("Classes:", classes.keys()) # This lists a whole bunch of classes, including lib/mpos/ stuff
|
||||
print("Functions:", functions.keys())
|
||||
print("Variables:", variables.keys())
|
||||
main_activity = script_globals.get(classname)
|
||||
if main_activity:
|
||||
from .app.activity import Activity
|
||||
from .content.intent import Intent
|
||||
start_time = utime.ticks_ms()
|
||||
Activity.startActivity(None, Intent(activity_class=main_activity))
|
||||
end_time = utime.ticks_diff(utime.ticks_ms(), start_time)
|
||||
print(f"execute_script: Activity.startActivity took {end_time}ms")
|
||||
else:
|
||||
print(f"Warning: could not find app's main_activity {classname}")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"Thread {thread_id}: exception during execution:")
|
||||
# Print stack trace with exception type, value, and traceback
|
||||
tb = getattr(e, '__traceback__', None)
|
||||
traceback.print_exception(type(e), e, tb)
|
||||
return False
|
||||
finally:
|
||||
# Always restore sys.path, even if we return early or raise an exception
|
||||
print(f"Thread {thread_id}: script {compile_name} finished, restoring sys.path from {sys.path} to {path_before}")
|
||||
sys.path = path_before
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Thread {thread_id}: error:")
|
||||
tb = getattr(e, '__traceback__', None)
|
||||
traceback.print_exception(type(e), e, tb)
|
||||
return False
|
||||
|
||||
# Returns True if successful
|
||||
def start_app(fullname):
|
||||
from .content.package_manager import PackageManager
|
||||
mpos.ui.set_foreground_app(fullname)
|
||||
import utime
|
||||
start_time = utime.ticks_ms()
|
||||
app = PackageManager.get(fullname)
|
||||
if not app:
|
||||
print(f"Warning: start_app can't find app {fullname}")
|
||||
return
|
||||
if not app.installed_path:
|
||||
print(f"Warning: start_app can't start {fullname} because no it doesn't have an installed_path")
|
||||
return
|
||||
entrypoint = "assets/main.py"
|
||||
classname = "Main"
|
||||
if not app.main_launcher_activity:
|
||||
print(f"WARNING: app {fullname} doesn't have a main_launcher_activity, defaulting to class {classname} in {entrypoint}")
|
||||
else:
|
||||
entrypoint = app.main_launcher_activity.get('entrypoint')
|
||||
classname = app.main_launcher_activity.get("classname")
|
||||
result = execute_script(app.installed_path + "/" + entrypoint, True, classname, app.installed_path + "/assets/")
|
||||
# Launchers have the bar, other apps don't have it
|
||||
if app.is_valid_launcher():
|
||||
mpos.ui.topmenu.open_bar()
|
||||
else:
|
||||
mpos.ui.topmenu.close_bar()
|
||||
end_time = utime.ticks_diff(utime.ticks_ms(), start_time)
|
||||
print(f"start_app() took {end_time}ms")
|
||||
return result
|
||||
|
||||
|
||||
# Starts the first launcher that's found
|
||||
def restart_launcher():
|
||||
from .content.package_manager import PackageManager
|
||||
print("restart_launcher")
|
||||
# Stop all apps
|
||||
mpos.ui.remove_and_stop_all_activities()
|
||||
# No need to stop the other launcher first, because it exits after building the screen
|
||||
return start_app(PackageManager.get_launcher().fullname)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
import traceback
|
||||
|
||||
try:
|
||||
import zipfile
|
||||
@@ -232,3 +233,115 @@ class PackageManager:
|
||||
print(f"Checking if app {app_fullname} is installed...")
|
||||
return PackageManager.is_installed_by_path(f"apps/{app_fullname}") or PackageManager.is_installed_by_path(f"builtin/apps/{app_fullname}")
|
||||
|
||||
@staticmethod
|
||||
def execute_script(script_source, is_file, classname, cwd=None):
|
||||
"""Run the script in the current thread. Returns True if successful."""
|
||||
import utime # for timing read and compile
|
||||
import lvgl as lv
|
||||
import mpos.ui
|
||||
import _thread
|
||||
thread_id = _thread.get_ident()
|
||||
compile_name = 'script' if not is_file else script_source
|
||||
print(f"Thread {thread_id}: executing script with cwd: {cwd}")
|
||||
try:
|
||||
if is_file:
|
||||
print(f"Thread {thread_id}: reading script from file {script_source}")
|
||||
with open(script_source, 'r') as f: # No need to check if it exists as exceptions are caught
|
||||
start_time = utime.ticks_ms()
|
||||
script_source = f.read()
|
||||
read_time = utime.ticks_diff(utime.ticks_ms(), start_time)
|
||||
print(f"execute_script: reading script_source took {read_time}ms")
|
||||
script_globals = {
|
||||
'lv': lv,
|
||||
'__name__': "__main__"
|
||||
}
|
||||
print(f"Thread {thread_id}: starting script")
|
||||
import sys
|
||||
path_before = sys.path[:] # Make a copy, not a reference
|
||||
if cwd:
|
||||
sys.path.append(cwd)
|
||||
try:
|
||||
start_time = utime.ticks_ms()
|
||||
compiled_script = compile(script_source, compile_name, 'exec')
|
||||
compile_time = utime.ticks_diff(utime.ticks_ms(), start_time)
|
||||
print(f"execute_script: compiling script_source took {compile_time}ms")
|
||||
start_time = utime.ticks_ms()
|
||||
exec(compiled_script, script_globals)
|
||||
end_time = utime.ticks_diff(utime.ticks_ms(), start_time)
|
||||
print(f"apps.py execute_script: exec took {end_time}ms")
|
||||
# Introspect globals
|
||||
classes = {k: v for k, v in script_globals.items() if isinstance(v, type)}
|
||||
functions = {k: v for k, v in script_globals.items() if callable(v) and not isinstance(v, type)}
|
||||
variables = {k: v for k, v in script_globals.items() if not callable(v)}
|
||||
print("Classes:", classes.keys()) # This lists a whole bunch of classes, including lib/mpos/ stuff
|
||||
print("Functions:", functions.keys())
|
||||
print("Variables:", variables.keys())
|
||||
main_activity = script_globals.get(classname)
|
||||
if main_activity:
|
||||
from ..app.activity import Activity
|
||||
from .intent import Intent
|
||||
start_time = utime.ticks_ms()
|
||||
Activity.startActivity(None, Intent(activity_class=main_activity))
|
||||
end_time = utime.ticks_diff(utime.ticks_ms(), start_time)
|
||||
print(f"execute_script: Activity.startActivity took {end_time}ms")
|
||||
else:
|
||||
print(f"Warning: could not find app's main_activity {classname}")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"Thread {thread_id}: exception during execution:")
|
||||
# Print stack trace with exception type, value, and traceback
|
||||
tb = getattr(e, '__traceback__', None)
|
||||
traceback.print_exception(type(e), e, tb)
|
||||
return False
|
||||
finally:
|
||||
# Always restore sys.path, even if we return early or raise an exception
|
||||
print(f"Thread {thread_id}: script {compile_name} finished, restoring sys.path from {sys.path} to {path_before}")
|
||||
sys.path = path_before
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Thread {thread_id}: error:")
|
||||
tb = getattr(e, '__traceback__', None)
|
||||
traceback.print_exception(type(e), e, tb)
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def start_app(fullname):
|
||||
"""Start an app by fullname. Returns True if successful."""
|
||||
import mpos.ui
|
||||
mpos.ui.set_foreground_app(fullname)
|
||||
import utime
|
||||
start_time = utime.ticks_ms()
|
||||
app = PackageManager.get(fullname)
|
||||
if not app:
|
||||
print(f"Warning: start_app can't find app {fullname}")
|
||||
return
|
||||
if not app.installed_path:
|
||||
print(f"Warning: start_app can't start {fullname} because no it doesn't have an installed_path")
|
||||
return
|
||||
entrypoint = "assets/main.py"
|
||||
classname = "Main"
|
||||
if not app.main_launcher_activity:
|
||||
print(f"WARNING: app {fullname} doesn't have a main_launcher_activity, defaulting to class {classname} in {entrypoint}")
|
||||
else:
|
||||
entrypoint = app.main_launcher_activity.get('entrypoint')
|
||||
classname = app.main_launcher_activity.get("classname")
|
||||
result = PackageManager.execute_script(app.installed_path + "/" + entrypoint, True, classname, app.installed_path + "/assets/")
|
||||
# Launchers have the bar, other apps don't have it
|
||||
if app.is_valid_launcher():
|
||||
mpos.ui.topmenu.open_bar()
|
||||
else:
|
||||
mpos.ui.topmenu.close_bar()
|
||||
end_time = utime.ticks_diff(utime.ticks_ms(), start_time)
|
||||
print(f"start_app() took {end_time}ms")
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def restart_launcher():
|
||||
"""Restart the launcher by stopping all activities and starting the launcher app."""
|
||||
import mpos.ui
|
||||
print("restart_launcher")
|
||||
# Stop all apps
|
||||
mpos.ui.remove_and_stop_all_activities()
|
||||
# No need to stop the other launcher first, because it exits after building the screen
|
||||
return PackageManager.start_app(PackageManager.get_launcher().fullname)
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import task_handler
|
||||
import _thread
|
||||
import lvgl as lv
|
||||
|
||||
import mpos.apps
|
||||
import mpos.ui
|
||||
import mpos.ui.topmenu
|
||||
|
||||
@@ -126,11 +125,11 @@ except Exception as e:
|
||||
|
||||
# Start launcher so it's always at bottom of stack
|
||||
launcher_app = PackageManager.get_launcher()
|
||||
started_launcher = mpos.apps.start_app(launcher_app.fullname)
|
||||
started_launcher = PackageManager.start_app(launcher_app.fullname)
|
||||
# Then start auto_start_app if configured
|
||||
auto_start_app = prefs.get_string("auto_start_app", None)
|
||||
if auto_start_app and launcher_app.fullname != auto_start_app:
|
||||
result = mpos.apps.start_app(auto_start_app)
|
||||
result = PackageManager.start_app(auto_start_app)
|
||||
if result is not True:
|
||||
print(f"WARNING: could not run {auto_start_app} app")
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import asyncio # this is the only place where asyncio is allowed to be imported - apps should not use it directly but use this TaskManager
|
||||
import _thread
|
||||
import mpos.apps
|
||||
|
||||
class TaskManager:
|
||||
|
||||
|
||||
@@ -815,13 +815,49 @@ class MockThread:
|
||||
|
||||
class MockApps:
|
||||
"""
|
||||
Mock mpos.apps module for testing.
|
||||
Mock mpos.apps module for testing (deprecated, use MockPackageManager instead).
|
||||
|
||||
This is kept for backward compatibility with existing tests.
|
||||
|
||||
Usage:
|
||||
sys.modules['mpos.apps'] = MockApps
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def good_stack_size():
|
||||
"""Return a reasonable stack size for testing."""
|
||||
return 8192
|
||||
def start_app(fullname):
|
||||
"""Mock start_app function."""
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def restart_launcher():
|
||||
"""Mock restart_launcher function."""
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def execute_script(script_source, is_file, classname, cwd=None):
|
||||
"""Mock execute_script function."""
|
||||
return True
|
||||
|
||||
|
||||
class MockPackageManager:
|
||||
"""
|
||||
Mock mpos.content.package_manager module for testing.
|
||||
|
||||
Usage:
|
||||
sys.modules['mpos.content.package_manager'] = MockPackageManager
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def start_app(fullname):
|
||||
"""Mock start_app function."""
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def restart_launcher():
|
||||
"""Mock restart_launcher function."""
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def execute_script(script_source, is_file, classname, cwd=None):
|
||||
"""Mock execute_script function."""
|
||||
return True
|
||||
@@ -13,9 +13,10 @@ infrastructure are already initialized (boot.py and main.py executed).
|
||||
|
||||
Usage in tests:
|
||||
from mpos.ui.testing import wait_for_render, capture_screenshot
|
||||
from mpos import PackageManager
|
||||
|
||||
# Start your app
|
||||
mpos.apps.start_app("com.example.myapp")
|
||||
PackageManager.start_app("com.example.myapp")
|
||||
|
||||
# Wait for UI to render
|
||||
wait_for_render()
|
||||
@@ -62,7 +63,8 @@ def wait_for_render(iterations=10):
|
||||
iterations: Number of task handler iterations to run (default: 10)
|
||||
|
||||
Example:
|
||||
mpos.apps.start_app("com.example.myapp")
|
||||
from mpos import PackageManager
|
||||
PackageManager.start_app("com.example.myapp")
|
||||
wait_for_render() # Ensure UI is ready
|
||||
assert verify_text_present(lv.screen_active(), "Welcome")
|
||||
"""
|
||||
|
||||
@@ -7,6 +7,7 @@ from .appearance_manager import AppearanceManager
|
||||
from .util import (get_foreground_app)
|
||||
from . import focus_direction
|
||||
from .widget_animator import WidgetAnimator
|
||||
from mpos.content.package_manager import PackageManager
|
||||
|
||||
CLOCK_UPDATE_INTERVAL = 1000 # 10 or even 1 ms doesn't seem to change the framerate but 100ms is enough
|
||||
WIFI_ICON_UPDATE_INTERVAL = 1500
|
||||
@@ -267,7 +268,7 @@ def create_drawer():
|
||||
wifi_label.center()
|
||||
def wifi_event(e):
|
||||
close_drawer()
|
||||
mpos.apps.start_app("com.micropythonos.wifi")
|
||||
PackageManager.start_app("com.micropythonos.wifi")
|
||||
wifi_btn.add_event_cb(wifi_event,lv.EVENT.CLICKED,None)
|
||||
settings_btn=lv.button(drawer)
|
||||
settings_btn.set_size(lv.pct(drawer_button_pct),lv.pct(20))
|
||||
@@ -277,7 +278,7 @@ def create_drawer():
|
||||
settings_label.center()
|
||||
def settings_event(e):
|
||||
close_drawer()
|
||||
mpos.apps.start_app("com.micropythonos.settings")
|
||||
PackageManager.start_app("com.micropythonos.settings")
|
||||
settings_btn.add_event_cb(settings_event,lv.EVENT.CLICKED,None)
|
||||
launcher_btn=lv.button(drawer)
|
||||
launcher_btn.set_size(lv.pct(drawer_button_pct),lv.pct(20))
|
||||
@@ -288,7 +289,7 @@ def create_drawer():
|
||||
def launcher_event(e):
|
||||
print("Launch button pressed!")
|
||||
close_drawer(True)
|
||||
mpos.apps.restart_launcher()
|
||||
PackageManager.restart_launcher()
|
||||
launcher_btn.add_event_cb(launcher_event,lv.EVENT.CLICKED,None)
|
||||
'''
|
||||
sleep_btn=lv.button(drawer)
|
||||
@@ -307,7 +308,7 @@ def create_drawer():
|
||||
else: # assume unix:
|
||||
# maybe do a system suspend here? or at least show a popup toast "not supported"
|
||||
close_drawer(True)
|
||||
mpos.apps.restart_launcher()
|
||||
PackageManager.restart_launcher()
|
||||
sleep_btn.add_event_cb(sleep_event,lv.EVENT.CLICKED,None)
|
||||
'''
|
||||
restart_btn=lv.button(drawer)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# lib/mpos/ui/util.py
|
||||
import lvgl as lv
|
||||
import sys
|
||||
from ..apps import restart_launcher
|
||||
|
||||
_foreground_app_name = None
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import lvgl as lv
|
||||
import sys
|
||||
|
||||
from ..apps import restart_launcher
|
||||
from .focus import save_and_clear_current_focusgroup
|
||||
from .topmenu import open_bar
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import _thread
|
||||
|
||||
from mpos.task_manager import TaskManager
|
||||
import mpos.apps
|
||||
|
||||
class Thread:
|
||||
def __init__(self, group=None, target=None, name=None, args=(), kwargs=None, daemon=None):
|
||||
|
||||
@@ -6,7 +6,6 @@ import time
|
||||
import unittest
|
||||
|
||||
from mpos import App, PackageManager
|
||||
import mpos.apps
|
||||
|
||||
from nostr.relay_manager import RelayManager
|
||||
from nostr.message_type import ClientMessageType
|
||||
|
||||
@@ -8,7 +8,6 @@ from mpos.testing import (
|
||||
MockPWM,
|
||||
MockPin,
|
||||
MockThread,
|
||||
MockApps,
|
||||
inject_mocks,
|
||||
)
|
||||
|
||||
@@ -16,7 +15,6 @@ from mpos.testing import (
|
||||
inject_mocks({
|
||||
'machine': MockMachine(),
|
||||
'_thread': MockThread,
|
||||
'mpos.apps': MockApps,
|
||||
})
|
||||
|
||||
# Now import the module to test
|
||||
|
||||
@@ -17,7 +17,6 @@ Usage:
|
||||
|
||||
import unittest
|
||||
import lvgl as lv
|
||||
import mpos.apps
|
||||
import mpos.ui
|
||||
import os
|
||||
from mpos import (
|
||||
@@ -27,7 +26,8 @@ from mpos import (
|
||||
verify_text_present,
|
||||
print_screen_labels,
|
||||
DeviceInfo,
|
||||
BuildInfo
|
||||
BuildInfo,
|
||||
PackageManager
|
||||
)
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ class TestGraphicalAboutApp(unittest.TestCase):
|
||||
print("\n=== Starting About app test ===")
|
||||
|
||||
# Start the About app
|
||||
result = mpos.apps.start_app("com.micropythonos.about")
|
||||
result = PackageManager.start_app("com.micropythonos.about")
|
||||
self.assertTrue(result, "Failed to start About app")
|
||||
|
||||
# Wait for UI to fully render
|
||||
@@ -146,7 +146,7 @@ class TestGraphicalAboutApp(unittest.TestCase):
|
||||
print("\n=== Starting About app OS version test ===")
|
||||
|
||||
# Start the About app
|
||||
result = mpos.apps.start_app("com.micropythonos.about")
|
||||
result = PackageManager.start_app("com.micropythonos.about")
|
||||
self.assertTrue(result, "Failed to start About app")
|
||||
|
||||
# Wait for UI to render
|
||||
|
||||
@@ -19,7 +19,6 @@ Usage:
|
||||
|
||||
import unittest
|
||||
import lvgl as lv
|
||||
import mpos.apps
|
||||
import mpos.ui
|
||||
import os
|
||||
import sys
|
||||
@@ -31,7 +30,8 @@ from mpos import (
|
||||
verify_text_present,
|
||||
print_screen_labels,
|
||||
simulate_click,
|
||||
get_widget_coords
|
||||
get_widget_coords,
|
||||
PackageManager
|
||||
)
|
||||
|
||||
@unittest.skipIf(sys.platform == 'darwin', "Camera tests not supported on macOS (no camera available)")
|
||||
@@ -117,7 +117,7 @@ class TestGraphicalCameraSettings(unittest.TestCase):
|
||||
print("\n=== Testing settings button click (no crash) ===")
|
||||
|
||||
# Start the Camera app
|
||||
result = mpos.apps.start_app("com.micropythonos.camera")
|
||||
result = PackageManager.start_app("com.micropythonos.camera")
|
||||
self.assertTrue(result, "Failed to start Camera app")
|
||||
|
||||
# Wait for camera to initialize and first frame to render
|
||||
@@ -251,7 +251,7 @@ class TestGraphicalCameraSettings(unittest.TestCase):
|
||||
print("\n=== Testing resolution change (no crash) ===")
|
||||
|
||||
# Start the Camera app
|
||||
result = mpos.apps.start_app("com.micropythonos.camera")
|
||||
result = PackageManager.start_app("com.micropythonos.camera")
|
||||
self.assertTrue(result, "Failed to start Camera app")
|
||||
|
||||
# Wait for camera to initialize
|
||||
|
||||
@@ -11,7 +11,6 @@ Usage:
|
||||
|
||||
import unittest
|
||||
import lvgl as lv
|
||||
import mpos.apps
|
||||
import mpos.ui
|
||||
import os
|
||||
import sys
|
||||
@@ -27,7 +26,8 @@ from mpos import (
|
||||
find_button_with_text,
|
||||
click_label,
|
||||
click_button,
|
||||
find_text_on_screen
|
||||
find_text_on_screen,
|
||||
PackageManager
|
||||
)
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ class TestIMUCalibration(unittest.TestCase):
|
||||
print("\n=== Testing CheckIMUCalibrationActivity ===")
|
||||
|
||||
# Navigate: Launcher -> Settings -> Check IMU Calibration
|
||||
result = mpos.apps.start_app("com.micropythonos.settings")
|
||||
result = PackageManager.start_app("com.micropythonos.settings")
|
||||
self.assertTrue(result, "Failed to start Settings app")
|
||||
wait_for_render(15)
|
||||
|
||||
@@ -98,7 +98,7 @@ class TestIMUCalibration(unittest.TestCase):
|
||||
print("\n=== Testing CalibrateIMUActivity Flow ===")
|
||||
|
||||
# Navigate: Launcher -> Settings -> Calibrate IMU
|
||||
result = mpos.apps.start_app("com.micropythonos.settings")
|
||||
result = PackageManager.start_app("com.micropythonos.settings")
|
||||
self.assertTrue(result, "Failed to start Settings app")
|
||||
wait_for_render(15)
|
||||
|
||||
@@ -155,7 +155,7 @@ class TestIMUCalibration(unittest.TestCase):
|
||||
print("\n=== Testing Check -> Calibrate Navigation ===")
|
||||
|
||||
# Navigate to Check activity
|
||||
result = mpos.apps.start_app("com.micropythonos.settings")
|
||||
result = PackageManager.start_app("com.micropythonos.settings")
|
||||
self.assertTrue(result)
|
||||
wait_for_render(15)
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ from mpos import (
|
||||
capture_screenshot,
|
||||
click_label,
|
||||
click_button,
|
||||
find_text_on_screen
|
||||
find_text_on_screen,
|
||||
PackageManager
|
||||
)
|
||||
|
||||
|
||||
@@ -43,10 +44,9 @@ class TestIMUCalibrationUI(unittest.TestCase):
|
||||
|
||||
# Step 2: Open Settings app
|
||||
print("Step 2: Opening Settings app...")
|
||||
import mpos.apps
|
||||
|
||||
# Start Settings app by name
|
||||
mpos.apps.start_app("com.micropythonos.settings")
|
||||
PackageManager.start_app("com.micropythonos.settings")
|
||||
wait_for_render(iterations=30)
|
||||
print("Settings app opened\n")
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import time
|
||||
# This is a graphical test - needs boot and main to run first
|
||||
# Add tests directory to path for helpers
|
||||
|
||||
from mpos import wait_for_render, apps, ui, PackageManager
|
||||
from mpos import wait_for_render, ui, PackageManager
|
||||
|
||||
|
||||
class TestLaunchAllApps(unittest.TestCase):
|
||||
@@ -64,7 +64,7 @@ class TestLaunchAllApps(unittest.TestCase):
|
||||
|
||||
try:
|
||||
# Launch the app by package name
|
||||
result = mpos.apps.start_app(package_name)
|
||||
result = PackageManager.start_app(package_name)
|
||||
|
||||
# Wait for UI to render
|
||||
wait_for_render(iterations=5)
|
||||
@@ -188,7 +188,7 @@ class TestLaunchSpecificApps(unittest.TestCase):
|
||||
|
||||
try:
|
||||
# Launch the app by package name
|
||||
result = mpos.apps.start_app(package_name)
|
||||
result = PackageManager.start_app(package_name)
|
||||
wait_for_render(iterations=5)
|
||||
|
||||
# Check if start_app returned False (indicates error)
|
||||
|
||||
@@ -13,7 +13,8 @@ from mpos import (
|
||||
verify_text_present,
|
||||
print_screen_labels,
|
||||
DeviceInfo,
|
||||
BuildInfo
|
||||
BuildInfo,
|
||||
PackageManager
|
||||
)
|
||||
|
||||
|
||||
@@ -28,7 +29,7 @@ class TestOSUpdateGraphicalUI(unittest.TestCase):
|
||||
|
||||
def test_app_launches_successfully(self):
|
||||
"""Test that OSUpdate app launches without errors."""
|
||||
result = mpos.apps.start_app("com.micropythonos.osupdate")
|
||||
result = PackageManager.start_app("com.micropythonos.osupdate")
|
||||
|
||||
self.assertTrue(result, "Failed to start OSUpdate app")
|
||||
wait_for_render(10)
|
||||
@@ -39,7 +40,7 @@ class TestOSUpdateGraphicalUI(unittest.TestCase):
|
||||
|
||||
def test_ui_elements_exist(self):
|
||||
"""Test that all required UI elements are created."""
|
||||
result = mpos.apps.start_app("com.micropythonos.osupdate")
|
||||
result = PackageManager.start_app("com.micropythonos.osupdate")
|
||||
self.assertTrue(result)
|
||||
wait_for_render(15)
|
||||
|
||||
@@ -59,7 +60,7 @@ class TestOSUpdateGraphicalUI(unittest.TestCase):
|
||||
|
||||
def test_force_checkbox_initially_unchecked(self):
|
||||
"""Test that force update checkbox starts unchecked."""
|
||||
result = mpos.apps.start_app("com.micropythonos.osupdate")
|
||||
result = PackageManager.start_app("com.micropythonos.osupdate")
|
||||
self.assertTrue(result)
|
||||
wait_for_render(15)
|
||||
|
||||
@@ -102,7 +103,7 @@ class TestOSUpdateGraphicalUI(unittest.TestCase):
|
||||
|
||||
def test_install_button_initially_disabled(self):
|
||||
"""Test that install button starts in disabled state."""
|
||||
result = mpos.apps.start_app("com.micropythonos.osupdate")
|
||||
result = PackageManager.start_app("com.micropythonos.osupdate")
|
||||
self.assertTrue(result)
|
||||
wait_for_render(15)
|
||||
|
||||
@@ -138,7 +139,7 @@ class TestOSUpdateGraphicalUI(unittest.TestCase):
|
||||
|
||||
def test_current_version_displayed(self):
|
||||
"""Test that current OS version is displayed correctly."""
|
||||
result = mpos.apps.start_app("com.micropythonos.osupdate")
|
||||
result = PackageManager.start_app("com.micropythonos.osupdate")
|
||||
self.assertTrue(result)
|
||||
wait_for_render(15)
|
||||
|
||||
@@ -158,7 +159,7 @@ class TestOSUpdateGraphicalUI(unittest.TestCase):
|
||||
"""Test status message when wifi is not connected."""
|
||||
# This test assumes desktop mode where wifi check returns True
|
||||
# On actual hardware without wifi, it would show error
|
||||
result = mpos.apps.start_app("com.micropythonos.osupdate")
|
||||
result = PackageManager.start_app("com.micropythonos.osupdate")
|
||||
self.assertTrue(result)
|
||||
wait_for_render(15)
|
||||
|
||||
@@ -173,7 +174,7 @@ class TestOSUpdateGraphicalUI(unittest.TestCase):
|
||||
|
||||
def test_screenshot_initial_state(self):
|
||||
"""Capture screenshot of initial app state."""
|
||||
result = mpos.apps.start_app("com.micropythonos.osupdate")
|
||||
result = PackageManager.start_app("com.micropythonos.osupdate")
|
||||
self.assertTrue(result)
|
||||
wait_for_render(20)
|
||||
|
||||
@@ -206,7 +207,7 @@ class TestOSUpdateGraphicalStatusMessages(unittest.TestCase):
|
||||
|
||||
def test_status_label_exists(self):
|
||||
"""Test that status label is created and visible."""
|
||||
result = mpos.apps.start_app("com.micropythonos.osupdate")
|
||||
result = PackageManager.start_app("com.micropythonos.osupdate")
|
||||
self.assertTrue(result)
|
||||
wait_for_render(15)
|
||||
|
||||
@@ -225,7 +226,7 @@ class TestOSUpdateGraphicalStatusMessages(unittest.TestCase):
|
||||
|
||||
def test_all_labels_readable(self):
|
||||
"""Test that all labels are readable (no truncation issues)."""
|
||||
result = mpos.apps.start_app("com.micropythonos.osupdate")
|
||||
result = PackageManager.start_app("com.micropythonos.osupdate")
|
||||
self.assertTrue(result)
|
||||
wait_for_render(15)
|
||||
|
||||
@@ -263,14 +264,14 @@ class TestOSUpdateGraphicalScreenshots(unittest.TestCase):
|
||||
|
||||
def test_capture_main_screen(self):
|
||||
"""Capture screenshot of main OSUpdate screen."""
|
||||
result = mpos.apps.start_app("com.micropythonos.osupdate")
|
||||
result = PackageManager.start_app("com.micropythonos.osupdate")
|
||||
self.assertTrue(result)
|
||||
wait_for_render(20)
|
||||
|
||||
|
||||
def test_capture_with_labels_visible(self):
|
||||
"""Capture screenshot ensuring all text is visible."""
|
||||
result = mpos.apps.start_app("com.micropythonos.osupdate")
|
||||
result = PackageManager.start_app("com.micropythonos.osupdate")
|
||||
self.assertTrue(result)
|
||||
wait_for_render(20)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user