Skip to content

Commit 6036c9c

Browse files
committed
Make sure errors and progress messages go to STDERR
Signed-off-by: Daniel J Walsh <[email protected]>
1 parent c62a2a4 commit 6036c9c

14 files changed

+42
-35
lines changed

ramalama/chat.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import urllib.request
1212
from datetime import timedelta
1313

14+
from ramalama.common import perror
1415
from ramalama.config import CONFIG
1516
from ramalama.console import EMOJI, should_colorize
1617
from ramalama.engine import dry_run, stop_container
@@ -68,7 +69,7 @@ def add_api_key(args, headers=None):
6869
if getattr(args, "api_key", None):
6970
api_key_min = 20
7071
if len(args.api_key) < api_key_min:
71-
print("Warning: Provided API key is invalid.")
72+
perror("Warning: Provided API key is invalid.")
7273

7374
headers["Authorization"] = f"Bearer {args.api_key}"
7475

@@ -161,7 +162,7 @@ def _req(self):
161162
break
162163
except Exception:
163164
if sys.stdout.isatty():
164-
print(f"\r{c}", end="", flush=True)
165+
perror(f"\r{c}", end="", flush=True)
165166

166167
if total_time_slept > max_timeout:
167168
break
@@ -176,7 +177,7 @@ def _req(self):
176177

177178
# Only show error and kill if not in initial connection phase
178179
if not getattr(self.args, "initial_connection", False):
179-
print(f"\rError: could not connect to: {self.url}", file=sys.stderr)
180+
perror(f"\rError: could not connect to: {self.url}")
180181
self.kills()
181182
else:
182183
logger.debug(f"Could not connect to: {self.url}")
@@ -251,7 +252,7 @@ def chat(args):
251252
except TimeoutException as e:
252253
logger.debug(f"Timeout Exception: {e}")
253254
# Handle the timeout, e.g., print a message and exit gracefully
254-
print("")
255+
perror("")
255256
pass
256257
finally:
257258
# Reset the alarm to 0 to cancel any pending alarms

ramalama/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ def list_files_by_modification(args):
382382
if os.path.exists(path):
383383
models.append(path)
384384
else:
385-
print(f"Broken symlink found in: {args.store}/models/{path} \nAttempting removal")
385+
perror(f"Broken symlink found in: {args.store}/models/{path} \nAttempting removal")
386386
New(str(path).replace("/", "://", 1), args).remove(args)
387387

388388
return sorted(models, key=lambda p: os.path.getmtime(p), reverse=True)

ramalama/common.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def confirm_no_gpu(name, provider) -> bool:
5454
return True
5555
if user_input in ["no", "n"]:
5656
return False
57-
print("Invalid input. Please enter 'yes' or 'no'.")
57+
perror("Invalid input. Please enter 'yes' or 'no'.")
5858

5959

6060
def handle_provider(machine, config: Config | None = None) -> bool | None:
@@ -580,7 +580,7 @@ def attempt_to_use_versioned(conman: str, image: str, vers: str, quiet: bool, sh
580580
try:
581581
# attempt to pull the versioned image
582582
if not quiet:
583-
print(f"Attempting to pull {image}:{vers} ...")
583+
perror(f"Attempting to pull {image}:{vers} ...")
584584
run_cmd([conman, "pull", f"{image}:{vers}"], ignore_stderr=True)
585585
return True
586586

ramalama/engine.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def add_pull_newer(self):
4747
if not self.args.dryrun and self.use_docker and self.args.pull == "newer":
4848
try:
4949
if not self.args.quiet:
50-
print(f"Checking for newer image {self.args.image}")
50+
perror(f"Checking for newer image {self.args.image}")
5151
run_cmd([str(self.args.engine), "pull", "-q", self.args.image], ignore_all=True)
5252
except Exception: # Ignore errors, the run command will handle it.
5353
pass

ramalama/hf_style_repo_base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ def pull(self, args):
220220
hash, cached_files, all = self.model_store.get_cached_files(tag)
221221
if all:
222222
if not args.quiet:
223-
print(f"Using cached {self.get_repo_type()}://{name}:{tag} ...")
223+
perror(f"Using cached {self.get_repo_type()}://{name}:{tag} ...")
224224
return self.model_store.get_snapshot_file_path(hash, name)
225225

226226
try:
@@ -252,4 +252,4 @@ def exec(self, cmd_args, args):
252252
try:
253253
exec_cmd(cmd_args)
254254
except FileNotFoundError as e:
255-
print(f"{str(e).strip()}\n{self.get_missing_message()}")
255+
perror(f"{str(e).strip()}\n{self.get_missing_message()}")

ramalama/http_client.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import os
44
import shutil
5+
import sys
56
import time
67
import urllib.request
78

ramalama/huggingface.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def get_repo_info(repo_name):
130130

131131
def handle_repo_info(repo_name, repo_info, runtime):
132132
if "safetensors" in repo_info and runtime == "llama.cpp":
133-
print(
133+
perror(
134134
"\nllama.cpp does not support running safetensor models, "
135135
"please use a/convert to the GGUF format using:\n"
136136
f"- https://huggingface.co/models?other=base_model:quantized:{repo_name} \n"

ramalama/model.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
check_nvidia,
2222
exec_cmd,
2323
genname,
24+
perror,
2425
set_accel_env_vars,
2526
)
2627
from ramalama.config import CONFIG, DEFAULT_PORT, DEFAULT_PORT_RANGE
@@ -188,7 +189,7 @@ def garbage_collection(self, args):
188189
if not file_has_a_symlink:
189190
os.remove(file_path)
190191
file_path = os.path.basename(file_path)
191-
print(f"Deleted: {file_path}")
192+
perror(f"Deleted: {file_path}")
192193

193194
def remove(self, args):
194195
_, tag, _ = self.extract_model_identifiers()
@@ -422,18 +423,16 @@ def _handle_mlx_chat(self, args):
422423
chat.chat(args)
423424
break
424425
else:
425-
if args.debug:
426-
print(f"MLX server not ready, waiting... (attempt {i+1}/{max_retries})", file=sys.stderr)
426+
logger.debug(f"MLX server not ready, waiting... (attempt {i+1}/{max_retries})")
427427
time.sleep(3)
428428
continue
429429

430430
except Exception as e:
431431
if i >= max_retries - 1:
432-
print(f"Error: Failed to connect to MLX server after {max_retries} attempts: {e}", file=sys.stderr)
432+
perror(f"Error: Failed to connect to MLX server after {max_retries} attempts: {e}")
433433
self._cleanup_server_process(args.pid2kill)
434434
raise e
435-
if args.debug:
436-
print(f"Connection attempt failed, retrying... (attempt {i+1}/{max_retries}): {e}", file=sys.stderr)
435+
logger.debug(f"Connection attempt failed, retrying... (attempt {i+1}/{max_retries}): {e}")
437436
time.sleep(3)
438437

439438
args.initial_connection = False
@@ -843,8 +842,9 @@ def inspect(self, args):
843842
print(ModelInfoBase(model_name, model_registry, model_path).serialize(json=args.json))
844843

845844
def print_pull_message(self, model_name):
846-
print(f"Downloading {model_name} ...")
847-
print(f"Trying to pull {model_name} ...")
845+
# Write messages to stderr
846+
perror(f"Downloading {model_name} ...")
847+
perror(f"Trying to pull {model_name} ...")
848848

849849

850850
def distinfo_volume():
@@ -894,7 +894,7 @@ def compute_serving_port(args, quiet=False) -> str:
894894
if not quiet:
895895
openai = f"http://localhost:{target_port}"
896896
if args.api == "llama-stack":
897-
print(f"Llama Stack RESTAPI: {openai}")
897+
perror(f"Llama Stack RESTAPI: {openai}")
898898
openai = openai + "/v1/openai"
899-
print(f"OpenAI RESTAPI: {openai}")
899+
perror(f"OpenAI RESTAPI: {openai}")
900900
return str(target_port)

ramalama/oci.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -311,12 +311,12 @@ def _create_manifest(self, target, imageid, args):
311311
run_cmd(cmd_args, stdout=None)
312312

313313
def _convert(self, source_model, args):
314-
print(f"Converting {source_model.model_store.base_path} to {self.model_store.base_path} ...")
314+
perror(f"Converting {source_model.model_store.base_path} to {self.model_store.base_path} ...")
315315
try:
316316
run_cmd([self.conman, "manifest", "rm", self.model], ignore_stderr=True, stdout=None)
317317
except subprocess.CalledProcessError:
318318
pass
319-
print(f"Building {self.model} ...")
319+
perror(f"Building {self.model} ...")
320320
imageid = self.build(source_model, args)
321321
try:
322322
self._create_manifest(self.model, imageid, args)
@@ -335,7 +335,7 @@ def push(self, source_model, args):
335335
target = self.model
336336
source = source_model.model
337337

338-
print(f"Pushing {self.model} ...")
338+
perror(f"Pushing {self.model} ...")
339339
conman_args = [self.conman, "push"]
340340
if args.authfile:
341341
conman_args.extend([f"--authfile={args.authfile}"])
@@ -351,14 +351,15 @@ def push(self, source_model, args):
351351
raise e
352352

353353
def pull(self, args):
354-
if not args.quiet:
355-
print(f"Downloading {self.model} ...")
356354
if not args.engine:
357355
raise NotImplementedError("OCI images require a container engine like Podman or Docker")
358356

359357
conman_args = [args.engine, "pull"]
360358
if args.quiet:
361359
conman_args.extend(['--quiet'])
360+
else:
361+
# Write message to stderr
362+
perror(f"Downloading {self.model} ...")
362363
if str(args.tlsverify).lower() == "false":
363364
conman_args.extend([f"--tls-verify={args.tlsverify}"])
364365
if args.authfile:

ramalama/ollama.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import urllib.error
44
from typing import Optional
55

6-
from ramalama.common import available
6+
from ramalama.common import available, perror
77
from ramalama.model import Model
88
from ramalama.model_store.snapshot_file import SnapshotFile, SnapshotFileType
99
from ramalama.ollama_repo_utils import fetch_manifest_data
@@ -147,7 +147,7 @@ def pull(self, args):
147147
hash, cached_files, all = self.model_store.get_cached_files(tag)
148148
if all:
149149
if not args.quiet:
150-
print(f"Using cached ollama://{name}:{tag} ...")
150+
perror(f"Using cached ollama://{name}:{tag} ...")
151151
return self.model_store.get_snapshot_file_path(hash, name)
152152

153153
ollama_repo = OllamaRepository(self.model_store.model_name)
@@ -165,7 +165,7 @@ def pull(self, args):
165165
# If a model has been downloaded via ollama cli, only create symlink in the snapshots directory
166166
if is_model_in_ollama_cache:
167167
if not args.quiet:
168-
print(f"Using cached ollama://{name}{tag} ...")
168+
perror(f"Using cached ollama://{name}{tag} ...")
169169
snapshot_model_path = self.model_store.get_snapshot_file_path(model_hash, self.model_store.model_name)
170170
os.symlink(ollama_cache_path, snapshot_model_path)
171171

0 commit comments

Comments
 (0)