Skip to content

Commit 66e680a

Browse files
authored
Don't raise warning when virtual environment already exists when trying to create a new one. (#3028)
* To prevent the error when trying to create a virtual environment that already exists, you can use the --allow-existing option with the uv venv command. This will allow you to bypass the error and use the existing environment instead. * When a plugin's pyproject.toml uses a build backend (e.g. poetry-core) but is not structured as an installable Python package, `uv pip install <gem_path>` fails during the build step. Add a fallback to pipinstall that uses `uv pip compile` to resolve and install the declared [project.dependencies] directly, bypassing the build backend entirely. Also fix pipinstall to return a non-zero exit code on failure, and update plugin_model.rb to check that exit code and emit a Logger.warn so installation failures surface in the COSMOS UI rather than being silently swallowed.
1 parent e31b7bc commit 66e680a

File tree

2 files changed

+47
-7
lines changed

2 files changed

+47
-7
lines changed

openc3/bin/pipinstall

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,45 @@
11
#!/bin/sh
2-
uv venv "$PYTHONUSERBASE"
2+
uv venv "$PYTHONUSERBASE" --allow-existing
33
echo "uv pip install $@"
44
uv pip install --python "$PYTHONUSERBASE" "$@"
55
if [ $? -eq 0 ]; then
66
echo "Command succeeded"
7-
else
8-
echo "Command failed - retrying with --no-index"
9-
uv pip install --python "$PYTHONUSERBASE" --no-index "$@"
10-
if [ $? -ne 0 ]; then
11-
echo "ERROR: uv pip install failed"
7+
exit 0
8+
fi
9+
10+
# Collect the last arg and all preceding args
11+
LAST_ARG=""
12+
OPTS=""
13+
PREV=""
14+
for ARG in "$@"; do
15+
if [ -n "$PREV" ]; then
16+
OPTS="${OPTS} ${PREV}"
17+
fi
18+
PREV="$ARG"
19+
done
20+
LAST_ARG="$PREV"
21+
22+
# If last arg is a directory with pyproject.toml, the build may have failed
23+
# (e.g. Poetry package-mode = false). Try compiling and installing declared
24+
# dependencies only, without attempting to build the package itself.
25+
if [ -d "$LAST_ARG" ] && [ -f "$LAST_ARG/pyproject.toml" ]; then
26+
echo "Warning: Failed to build Python package, attempting to install declared dependencies from pyproject.toml"
27+
TMPFILE=$(mktemp)
28+
uv pip compile ${OPTS} "${LAST_ARG}/pyproject.toml" > "$TMPFILE"
29+
if [ $? -eq 0 ] && [ -s "$TMPFILE" ]; then
30+
uv pip install --python "$PYTHONUSERBASE" ${OPTS} -r "$TMPFILE"
31+
if [ $? -eq 0 ]; then
32+
echo "Dependencies installed successfully"
33+
rm -f "$TMPFILE"
34+
exit 0
35+
fi
1236
fi
37+
rm -f "$TMPFILE"
38+
fi
39+
40+
echo "Warning: Install failed - retrying with --no-index"
41+
uv pip install --python "$PYTHONUSERBASE" --no-index "$@"
42+
if [ $? -ne 0 ]; then
43+
echo "ERROR: uv pip install failed"
44+
exit 1
1345
fi

openc3/lib/openc3/models/plugin_model.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,15 @@ def self.install_phase2(plugin_hash, scope:, gem_file_path: nil, validate_only:
280280
pip_args = "-i #{pypi_url} --trusted-host #{URI.parse(pypi_url).host} -r #{requirements_path}"
281281
end
282282
end
283-
puts `/openc3/bin/pipinstall #{pip_args}`
283+
# Capture output and check exit code so failures surface as a warning
284+
# rather than silently succeeding. pipinstall is non-fatal: the plugin
285+
# continues to install even if Python packages fail so that non-Python
286+
# functionality still works.
287+
output = `/openc3/bin/pipinstall #{pip_args}`
288+
puts output
289+
unless $?.success?
290+
Logger.warn "Python package installation failed. Plugin Python microservices may not function correctly."
291+
end
284292
end
285293
needs_dependencies = true
286294
end

0 commit comments

Comments
 (0)