Skip to content

Commit 1d471af

Browse files
Change parse_manifest() to App.from_manifest()
1 parent 88b06ae commit 1d471af

File tree

2 files changed

+91
-63
lines changed

2 files changed

+91
-63
lines changed

internal_filesystem/lib/mpos/apps.py

Lines changed: 90 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,23 @@ def restart_launcher():
143143
break
144144

145145
class App:
146-
def __init__(self, name, publisher, short_description, long_description, icon_url, download_url, fullname, version, category, activities, installed_path=None):
146+
# ------------------------------------------------------------------ #
147+
# Regular constructor – use when you already have the data
148+
# ------------------------------------------------------------------ #
149+
def __init__(
150+
self,
151+
name="Unknown",
152+
publisher="Unknown",
153+
short_description="",
154+
long_description="",
155+
icon_url="",
156+
download_url="",
157+
fullname="Unknown",
158+
version="0.0.0",
159+
category="",
160+
activities=None,
161+
installed_path=None,
162+
):
147163
self.name = name
148164
self.publisher = publisher
149165
self.short_description = short_description
@@ -153,79 +169,91 @@ def __init__(self, name, publisher, short_description, long_description, icon_ur
153169
self.fullname = fullname
154170
self.version = version
155171
self.category = category
172+
self.activities = activities if activities is not None else []
173+
self.installed_path = installed_path
174+
175+
# Cached image fields (kept for compatibility)
156176
self.image = None
157177
self.image_dsc = None
158-
self.activities = activities
159-
self.installed_path = installed_path
178+
179+
# Find the main launcher activity once, at construction time
160180
self.main_launcher_activity = self._find_main_launcher_activity()
161181

182+
# ------------------------------------------------------------------ #
183+
# Human-readable representation
184+
# ------------------------------------------------------------------ #
162185
def __str__(self):
163-
return (f"App(name='{self.name}', "
164-
f"publisher='{self.publisher}', "
165-
f"short_description='{self.short_description}', "
166-
f"version='{self.version}', "
167-
f"category='{self.category}', "
168-
f"activities='{self.activities}', "
169-
f"installed_path={self.installed_path})")
170-
186+
return (
187+
f"App(name='{self.name}', "
188+
f"publisher='{self.publisher}', "
189+
f"short_description='{self.short_description}', "
190+
f"version='{self.version}', "
191+
f"category='{self.category}', "
192+
f"activities={len(self.activities)} items, "
193+
f"installed_path={self.installed_path})"
194+
)
195+
196+
# ------------------------------------------------------------------ #
197+
# Private helper – locate the MAIN/LAUNCHER activity
198+
# ------------------------------------------------------------------ #
171199
def _find_main_launcher_activity(self):
172-
result = None
173200
for activity in self.activities:
174201
if not activity.get("entrypoint") or not activity.get("classname"):
175-
print(f"Warning: activity {activity} has no entrypoint and classname, skipping...")
202+
print("Warning: activity missing entrypoint or classnameskipping")
176203
continue
177-
print("checking activity's intent_filters...")
178-
for intent_filter in activity.get("intent_filters"):
179-
print("checking intent_filter...")
180-
if intent_filter.get("action") == "main" and intent_filter.get("category") == "launcher":
181-
print("found main_launcher!")
182-
result = activity
183-
break
184-
return result
185204

205+
for intent_filter in activity.get("intent_filters", []):
206+
if (
207+
intent_filter.get("action") == "main"
208+
and intent_filter.get("category") == "launcher"
209+
):
210+
print("Found main launcher activity!")
211+
return activity
212+
return None
213+
214+
# ------------------------------------------------------------------ #
215+
# Convenience check for launcher-type apps
216+
# ------------------------------------------------------------------ #
186217
def is_valid_launcher(self):
187-
#print(f"checking is_valid_launcher for {app_obj}")
188-
return self.category == "launcher" and self.main_launcher_activity
189-
218+
return self.category == "launcher" and self.main_launcher_activity is not None
219+
220+
# ------------------------------------------------------------------ #
221+
# Class-method constructor that builds an App from a manifest file
222+
# ------------------------------------------------------------------ #
223+
@classmethod
224+
def from_manifest(cls, appdir):
225+
"""
226+
Parse <appdir>/META-INF/MANIFEST.JSON and return a fully-populated
227+
App instance. If the file cannot be read, a default App with
228+
placeholder values is returned.
229+
"""
230+
print(f"parse_manifest({appdir})")
231+
manifest_path = f"{appdir}/META-INF/MANIFEST.JSON"
232+
233+
# Minimal default instance – guarantees every field has a fallback
234+
default = cls(installed_path=appdir)
190235

191-
def parse_manifest(appdir):
192-
print(f"parse_manifest({appdir})")
193-
manifest_path = f"{appdir}/META-INF/MANIFEST.JSON"
194-
# Default values for App object
195-
default_app = App(
196-
name="Unknown",
197-
publisher="Unknown",
198-
short_description="",
199-
long_description="",
200-
icon_url="",
201-
download_url="",
202-
fullname="Unknown",
203-
version="0.0.0",
204-
category="",
205-
activities=[],
206-
installed_path=appdir
207-
)
208-
try:
209-
with open(manifest_path, 'r') as f:
210-
app_info = ujson.load(f)
211-
#print(f"parsed app: {app_info}")
212-
# Create App object with values from manifest, falling back to defaults
213-
return App(
214-
name=app_info.get("name", default_app.name),
215-
publisher=app_info.get("publisher", default_app.publisher),
216-
short_description=app_info.get("short_description", default_app.short_description),
217-
long_description=app_info.get("long_description", default_app.long_description),
218-
icon_url=app_info.get("icon_url", default_app.icon_url),
219-
download_url=app_info.get("download_url", default_app.download_url),
220-
fullname=app_info.get("fullname", default_app.fullname),
221-
version=app_info.get("version", default_app.version),
222-
category=app_info.get("category", default_app.category),
223-
activities=app_info.get("activities", default_app.activities),
224-
installed_path=appdir
225-
)
226-
except OSError:
227-
print(f"parse_manifest: error loading manifest_path: {manifest_path}")
228-
return default_app
236+
try:
237+
with open(manifest_path, "r") as f:
238+
data = ujson.load(f)
239+
except OSError as exc:
240+
print(f"parse_manifest: error loading {manifest_path}{exc}")
241+
return default
242+
243+
# Merge manifest data with defaults
244+
return cls(
245+
name=data.get("name", default.name),
246+
publisher=data.get("publisher", default.publisher),
247+
short_description=data.get("short_description", default.short_description),
248+
long_description=data.get("long_description", default.long_description),
249+
icon_url=data.get("icon_url", default.icon_url),
250+
download_url=data.get("download_url", default.download_url),
251+
fullname=data.get("fullname", default.fullname),
252+
version=data.get("version", default.version),
253+
category=data.get("category", default.category),
254+
activities=data.get("activities", default.activities),
255+
installed_path=appdir,
256+
)
229257

230258

231259
class Activity:

internal_filesystem/lib/mpos/package_manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ def refresh_apps(cls):
121121

122122
# ---- parse the manifest ---------------------------------
123123
try:
124-
app = mpos.apps.parse_manifest(full_path)
124+
app = mpos.apps.App.from_manifest(full_path)
125125
except Exception as e:
126126
print("PackageManager: parsing {} failed: {}".format(full_path, e))
127127
continue

0 commit comments

Comments
 (0)