refactor: optimize library search and installation methods for improved performance and error handling

pull/10/head
David Montero Crespo 2026-03-04 23:17:23 -03:00
parent 426c7ab35f
commit 9925d8b31e
1 changed files with 65 additions and 54 deletions

View File

@ -203,28 +203,39 @@ class ArduinoCLIService:
Search for Arduino libraries Search for Arduino libraries
""" """
try: try:
# arduino-cli lib search <query> --format json def _run():
process = await asyncio.create_subprocess_exec( return subprocess.run(
self.cli_path, [self.cli_path, "lib", "search", query, "--format", "json"],
"lib", capture_output=True, text=True, encoding='utf-8', errors='replace'
"search", )
query,
"--format", "json",
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
stdout, stderr = await process.communicate() result = await asyncio.to_thread(_run)
stdout, stderr = result.stdout, result.stderr
if process.returncode != 0: if result.returncode != 0:
print(f"Error searching libraries: {stderr.decode()}") print(f"Error searching libraries: {stderr}")
return {"success": False, "error": stderr.decode()} return {"success": False, "error": stderr}
import json import json
try: try:
results = json.loads(stdout.decode()) results = json.loads(stdout)
# The arduino-cli JSON output for search usually contains a "libraries" array
libraries = results.get("libraries", []) libraries = results.get("libraries", [])
# arduino-cli search returns each lib with a "releases" dict.
# Inject a "latest" key with the data of the highest version so the
# frontend can access lib.latest.version / author / sentence directly.
def _parse_version(v: str):
try:
return tuple(int(x) for x in v.split("."))
except Exception:
return (0,)
for lib in libraries:
releases = lib.get("releases") or {}
if releases:
latest_key = max(releases.keys(), key=_parse_version)
lib["latest"] = {**releases[latest_key], "version": latest_key}
return {"success": True, "libraries": libraries} return {"success": True, "libraries": libraries}
except json.JSONDecodeError: except json.JSONDecodeError:
return {"success": False, "error": "Invalid output format from arduino-cli"} return {"success": False, "error": "Invalid output format from arduino-cli"}
@ -239,24 +250,21 @@ class ArduinoCLIService:
""" """
try: try:
print(f"Installing library: {library_name}") print(f"Installing library: {library_name}")
# arduino-cli lib install <name>
process = await asyncio.create_subprocess_exec(
self.cli_path,
"lib",
"install",
library_name,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
stdout, stderr = await process.communicate() def _run():
return subprocess.run(
[self.cli_path, "lib", "install", library_name],
capture_output=True, text=True, encoding='utf-8', errors='replace'
)
if process.returncode == 0: result = await asyncio.to_thread(_run)
if result.returncode == 0:
print(f"Successfully installed {library_name}") print(f"Successfully installed {library_name}")
return {"success": True, "stdout": stdout.decode()} return {"success": True, "stdout": result.stdout}
else: else:
print(f"Failed to install {library_name}: {stderr.decode()}") print(f"Failed to install {library_name}: {result.stderr}")
return {"success": False, "error": stderr.decode(), "stdout": stdout.decode()} return {"success": False, "error": result.stderr, "stdout": result.stdout}
except Exception as e: except Exception as e:
print(f"Exception installing library: {e}") print(f"Exception installing library: {e}")
@ -267,36 +275,39 @@ class ArduinoCLIService:
List all installed Arduino libraries List all installed Arduino libraries
""" """
try: try:
# arduino-cli lib list --format json def _run():
process = await asyncio.create_subprocess_exec( return subprocess.run(
self.cli_path, [self.cli_path, "lib", "list", "--format", "json"],
"lib", capture_output=True, text=True, encoding='utf-8', errors='replace'
"list", )
"--format", "json",
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
stdout, stderr = await process.communicate() result = await asyncio.to_thread(_run)
stdout, stderr = result.stdout, result.stderr
if process.returncode != 0: if result.returncode != 0:
print(f"Error listing libraries: {stderr.decode()}") print(f"Error listing libraries: {stderr}")
return {"success": False, "error": stderr.decode()} return {"success": False, "error": stderr}
import json import json
try: try:
# The output when no libraries are found might be empty or different
if not stdout.strip(): if not stdout.strip():
return {"success": True, "libraries": []} return {"success": True, "libraries": []}
results = json.loads(stdout.decode()) results = json.loads(stdout)
# Should be a list directly or a dict with lists inside, check both forms
# arduino-cli lib list --format json wraps results in "installed_libraries"
if isinstance(results, list): if isinstance(results, list):
return {"success": True, "libraries": results} libraries = results
elif isinstance(results, dict) and "libraries" in results: elif isinstance(results, dict):
return {"success": True, "libraries": results.get("libraries", [])} libraries = (
results.get("installed_libraries")
or results.get("libraries")
or []
)
else: else:
return {"success": True, "libraries": results} # Best effort fallback libraries = []
return {"success": True, "libraries": libraries}
except json.JSONDecodeError: except json.JSONDecodeError:
return {"success": False, "error": "Invalid output format from arduino-cli"} return {"success": False, "error": "Invalid output format from arduino-cli"}