Skip to content

Commit cea4e59

Browse files
PackageManager: add dictionary for easy package lookup
1 parent 73497d8 commit cea4e59

File tree

2 files changed

+84
-29
lines changed

2 files changed

+84
-29
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ def toggle_install(self, download_url, fullname):
312312
print("Uninstalling app....")
313313
try:
314314
_thread.stack_size(mpos.apps.good_stack_size())
315-
_thread.start_new_thread(self.uninstall_app, (fullname))
315+
_thread.start_new_thread(self.uninstall_app, (fullname,))
316316
except Exception as e:
317317
print("Could not start uninstall_app thread: ", e)
318318

@@ -349,7 +349,7 @@ def download_and_install(self, zip_url, dest_folder, app_fullname):
349349
try:
350350
# Step 1: Download the .mpk file
351351
print(f"Downloading .mpk file from: {zip_url}")
352-
response = requests.get(zip_url, timeout=10)
352+
response = requests.get(zip_url, timeout=10) # TODO: use stream=True and do it in chunks like in OSUpdate
353353
if response.status_code != 200:
354354
print("Download failed: Status code", response.status_code)
355355
response.close()

internal_filesystem/lib/mpos/package_manager.py

Lines changed: 82 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -28,50 +28,105 @@
2828
2929
'''
3030

31+
# PackageManager.py (MicroPython)
3132

32-
class PackageManager():
33+
import os
34+
35+
class PackageManager:
36+
"""Registry of all discovered apps.
37+
38+
* PackageManager.get_app_list() -> list of App objects (sorted by name)
39+
* PackageManager[fullname] -> App (raises KeyError if missing)
40+
* PackageManager.get(fullname) -> App or None
41+
"""
3342

34-
app_list = [] # list of App objects, sorted alphabetically by app.name, unique by full_name (com.example.appname)
43+
# --------------------------------------------------------------------- #
44+
# internal storage
45+
# --------------------------------------------------------------------- #
46+
_app_list = [] # sorted by app.name
47+
_by_fullname = {} # fullname -> App
3548

49+
# --------------------------------------------------------------------- #
50+
# public list access (kept for backward compatibility)
51+
# --------------------------------------------------------------------- #
3652
@classmethod
3753
def get_app_list(cls):
38-
if len(cls.app_list) == 0:
54+
if not cls._app_list:
3955
cls.find_apps()
40-
return cls.app_list
56+
return cls._app_list
57+
58+
# --------------------------------------------------------------------- #
59+
# dict-style lookup: PackageManager["com.example.myapp"]
60+
# --------------------------------------------------------------------- #
61+
def __class_getitem__(cls, fullname):
62+
try:
63+
return cls._by_fullname[fullname]
64+
except KeyError:
65+
raise KeyError("No app with fullname='{}'".format(fullname))
4166

67+
# --------------------------------------------------------------------- #
68+
# safe lookup: PackageManager.get("com.example.myapp") -> App or None
69+
# --------------------------------------------------------------------- #
70+
@classmethod
71+
def get(cls, fullname):
72+
return cls._by_fullname.get(fullname)
73+
74+
# --------------------------------------------------------------------- #
75+
# discovery & population
76+
# --------------------------------------------------------------------- #
4277
@classmethod
4378
def find_apps(cls):
4479
print("\n\n\nPackageManager finding apps...")
45-
seen_fullnames = set()
46-
# Check and collect subdirectories from existing directories
47-
apps_dir = "apps"
80+
81+
seen = set() # avoid processing the same fullname twice
82+
apps_dir = "apps"
4883
apps_dir_builtin = "builtin/apps"
4984

50-
# Check and collect unique subdirectories
51-
for dir_path in [apps_dir, apps_dir_builtin]:
85+
for base in (apps_dir, apps_dir_builtin):
5286
try:
53-
if os.stat(dir_path)[0] & 0x4000: # Verify directory exists
87+
# ---- does the directory exist? --------------------------------
88+
st = os.stat(base)
89+
if not (st[0] & 0x4000): # 0x4000 = directory bit
90+
continue
91+
92+
# ---- iterate over immediate children -------------------------
93+
for name in os.listdir(base):
94+
full_path = "{}/{}".format(base, name)
95+
96+
# ---- is it a directory? ---------------------------------
5497
try:
55-
for d in os.listdir(dir_path):
56-
full_path = f"{dir_path}/{d}"
57-
print(f"full_path: {full_path}")
58-
try:
59-
if os.stat(full_path)[0] & 0x4000: # Check if it's a directory
60-
fullname = d
61-
if fullname not in seen_fullnames: # Avoid duplicates
62-
seen_fullnames.add(fullname)
63-
app = mpos.apps.parse_manifest(full_path)
64-
cls.app_list.append(app)
65-
print(f"added app {app}")
66-
except Exception as e:
67-
print(f"PackageManager: stat of {full_path} got exception: {e}")
98+
st = os.stat(full_path)
99+
if not (st[0] & 0x4000):
100+
continue
68101
except Exception as e:
69-
print(f"PackageManager: listdir of {dir_path} got exception: {e}")
102+
print("PackageManager: stat of {} got exception: {}".format(full_path, e))
103+
continue
104+
105+
fullname = name
106+
107+
# ---- skip duplicates ------------------------------------
108+
if fullname in seen:
109+
continue
110+
seen.add(fullname)
111+
112+
# ---- parse the manifest ---------------------------------
113+
try:
114+
app = mpos.apps.parse_manifest(full_path)
115+
except Exception as e:
116+
print("PackageManager: parsing {} failed: {}".format(full_path, e))
117+
continue
118+
119+
# ---- store in both containers ---------------------------
120+
cls._app_list.append(app)
121+
cls._by_fullname[fullname] = app
122+
print("added app {}".format(app))
123+
70124
except Exception as e:
71-
print(f"PackageManager: stat of {dir_path} got exception: {e}")
125+
print("PackageManager: handling {} got exception: {}".format(base, e))
126+
127+
# ---- sort the list by display name (case-insensitive) ------------
128+
cls._app_list.sort(key=lambda a: a.name.lower())
72129

73-
# Sort apps alphabetically by app.name
74-
cls.app_list.sort(key=lambda x: x.name.lower()) # Case-insensitive sorting by name
75130

76131
@staticmethod
77132
def uninstall_app(app_fullname):

0 commit comments

Comments
 (0)