Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/pieces/command_interface/config_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ def get_examples(self):
"pieces config --editor nvim", "Set Neovim as default editor"
).example("pieces config --editor vim", "Set Vim as default editor")

builder.section(
header="PiecesOS Launch:",
command_template="pieces config --auto-launch-pieces-os",
).example(
"pieces config --auto-launch-pieces-os",
"Enable automatic PiecesOS startup when a command needs it",
).example(
"pieces config --no-auto-launch-pieces-os",
"Disable automatic PiecesOS startup",
)

return builder.build()

def get_docs(self) -> str:
Expand All @@ -52,15 +63,31 @@ def add_arguments(self, parser: argparse.ArgumentParser):
type=str,
help="Set the default code editor",
)
parser.add_argument(
"--auto-launch-pieces-os",
dest="auto_launch_pieces_os",
action=argparse.BooleanOptionalAction,
default=None,
help="Automatically launch PiecesOS when a command requires it",
)
Comment thread
anthony-maio marked this conversation as resolved.

def execute(self, **kwargs) -> int:
"""Execute the config command."""

editor = kwargs.get("editor")
auto_launch = kwargs.get("auto_launch_pieces_os")
if editor:
Settings.cli_config.editor = editor
Settings.logger.print(f"Editor set to: {editor}")
elif auto_launch is not None:
Settings.cli_config.auto_launch_pieces_os = auto_launch
Comment thread
anthony-maio marked this conversation as resolved.
status = "Enabled" if auto_launch else "Disabled"
Settings.logger.print(f"Auto-launch PiecesOS: {status}")
else:
Comment thread
anthony-maio marked this conversation as resolved.
Outdated
Settings.logger.print("Current configuration:")
Settings.logger.print(f"Editor: {Settings.cli_config.editor or 'Not set'}")
Settings.logger.print(
"Auto-launch PiecesOS: "
+ ("Enabled" if Settings.cli_config.auto_launch_pieces_os else "Disabled")
)
return 0
11 changes: 11 additions & 0 deletions src/pieces/config/managers/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,14 @@ def theme(self, value: str) -> None:
self.config.theme = value
self.save()

@property
def auto_launch_pieces_os(self) -> bool:
"""Get whether the CLI should auto-launch PiecesOS."""
return self.config.auto_launch_pieces_os

@auto_launch_pieces_os.setter
def auto_launch_pieces_os(self, value: bool) -> None:
"""Set whether the CLI should auto-launch PiecesOS."""
self.config.auto_launch_pieces_os = value
self.save()

6 changes: 5 additions & 1 deletion src/pieces/config/schemas/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ class CLIConfigSchema(BaseModel):
)
editor: Optional[str] = Field(default=None, description="Default editor command")
theme: str = Field(default="pieces-dark", description="TUI theme preference")
auto_launch_pieces_os: bool = Field(
default=True,
description="Automatically launch PiecesOS when a CLI command requires it",
)

@field_validator("editor")
@classmethod
Expand All @@ -27,4 +31,4 @@ def validate_editor(cls, v):
@field_validator('schema_version', mode='before')
@classmethod
def validate_semver_field(cls, v):
return validate_semver(v)
return validate_semver(v)
10 changes: 9 additions & 1 deletion src/pieces/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,16 @@ def startup(cls, bypass_login=False):
os_id = cls.get_os_id()
sentry_sdk.set_user({"id": os_id or "unknown"})
else:
if cls.pieces_client.is_pieces_running() or cls.open_pieces_widget():
if cls.pieces_client.is_pieces_running() or (
cls.cli_config.auto_launch_pieces_os and cls.open_pieces_widget()
):
Comment thread
anthony-maio marked this conversation as resolved.
Outdated
return cls.startup(bypass_login)
if not cls.cli_config.auto_launch_pieces_os:
cls.logger.print(
"PiecesOS is required but isn't running.\n"
"Start it manually or enable auto-launch with `pieces config --auto-launch-pieces-os`."
)
sys.exit(2)
if cls.logger.confirm(
"Pieces OS is required but wasn’t found or couldn’t be launched.\n"
"Do you want to install it now and get started?"
Expand Down
52 changes: 52 additions & 0 deletions tests/config_command_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import pytest
from unittest.mock import Mock, patch
Comment thread
anthony-maio marked this conversation as resolved.
Outdated

from pieces.command_interface.config_command import ConfigCommand
from pieces.settings import Settings


REAL_SETTINGS_STARTUP = Settings.startup.__func__


class TestConfigCommand:
@pytest.fixture
def config_command(self):
return ConfigCommand()

@patch.object(Settings, "logger")
@patch.object(Settings, "cli_config")
def test_execute_sets_auto_launch_pieces_os(
self, mock_cli_config, mock_logger, config_command
):
result = config_command.execute(auto_launch_pieces_os=False)

assert result == 0
assert mock_cli_config.auto_launch_pieces_os is False
mock_logger.print.assert_called_once()
assert "auto-launch" in mock_logger.print.call_args[0][0].lower()
Comment thread
anthony-maio marked this conversation as resolved.


class TestSettingsStartup:
@patch("sys.exit", side_effect=SystemExit(2))
@patch.object(Settings, "logger")
@patch.object(Settings, "cli_config")
@patch.object(Settings, "pieces_client")
@patch.object(Settings, "open_pieces_widget")
def test_startup_skips_launch_when_auto_launch_disabled(
self,
mock_open_pieces_widget,
mock_pieces_client,
mock_cli_config,
mock_logger,
mock_sys_exit,
):
mock_cli_config.auto_launch_pieces_os = False
mock_pieces_client.is_pieces_running.return_value = False
mock_logger.confirm.return_value = False

with pytest.raises(SystemExit):
REAL_SETTINGS_STARTUP(Settings, bypass_login=False)

mock_open_pieces_widget.assert_not_called()
mock_logger.print.assert_called()
assert "enable auto-launch" in mock_logger.print.call_args_list[-1][0][0].lower()
Loading