Skip to content

Commit b195abc

Browse files
committed
feat: global config path support
- config now persists to ~/.config/o2switch-cli/.env by default - local .env still takes precedence if it exists - added config path command to show active/global/local paths - config show now displays the active config file
1 parent 6107d01 commit b195abc

2 files changed

Lines changed: 40 additions & 6 deletions

File tree

‎o2switch_cli/cli/config_cmd.py‎

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from o2switch_cli.cli.helpers import run_guarded
99
from o2switch_cli.cli.ui import TerminalUI
10-
from o2switch_cli.config.settings import AppSettings, default_audit_log_path, settings_summary, write_env_file
10+
from o2switch_cli.config.settings import AppSettings, default_audit_log_path, find_env_file, global_config_path, settings_summary, write_env_file
1111
from o2switch_cli.core.errors import ValidationAppError
1212

1313
app = typer.Typer(help="Inspect active configuration and API reachability.", rich_markup_mode="rich")
@@ -17,7 +17,26 @@
1717
def show_config(ctx: typer.Context) -> None:
1818
def action(app_context):
1919
ui = TerminalUI(app_context.console, app_context.output_format)
20-
ui.print_mapping("Active Configuration", settings_summary(app_context.settings))
20+
summary = settings_summary(app_context.settings)
21+
summary["config_file"] = find_env_file() or "(none found)"
22+
ui.print_mapping("Active Configuration", summary)
23+
24+
run_guarded(ctx, action)
25+
26+
27+
@app.command("path")
28+
def show_path(ctx: typer.Context) -> None:
29+
"""Show configuration file paths."""
30+
def action(app_context):
31+
ui = TerminalUI(app_context.console, app_context.output_format)
32+
ui.print_mapping(
33+
"Config Paths",
34+
{
35+
"active": find_env_file() or "(none)",
36+
"global": str(global_config_path()),
37+
"local": str(Path(".env").resolve()),
38+
},
39+
)
2140

2241
run_guarded(ctx, action)
2342

@@ -42,7 +61,7 @@ def action(app_context):
4261
@app.command("init")
4362
def init_config(
4463
ctx: typer.Context,
45-
path: Path = typer.Option(Path(".env"), "--path", help="Write credentials and defaults to this dotenv file."),
64+
path: Path | None = typer.Option(None, "--path", help="Write credentials to this file. Defaults to global config."),
4665
cpanel_host: str | None = typer.Option(None, "--cpanel-host", help="cPanel host, for example saule.o2switch.net."),
4766
cpanel_user: str | None = typer.Option(None, "--cpanel-user", help="cPanel username."),
4867
cpanel_token: str | None = typer.Option(None, "--cpanel-token", help="cPanel API token."),
@@ -61,7 +80,7 @@ def init_config(
6180
def action(app_context):
6281
ui = TerminalUI(app_context.console, app_context.output_format)
6382
current = app_context.settings
64-
target = path.expanduser().resolve()
83+
target = (path or global_config_path()).expanduser().resolve()
6584

6685
if target.exists() and not force and not non_interactive:
6786
if not ui.confirm(f"{target} already exists. Overwrite it?"):

‎o2switch_cli/config/settings.py‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from pathlib import Path
66
from typing import Any, Literal
77

8-
from platformdirs import user_state_dir
8+
from platformdirs import user_config_dir, user_state_dir
99
from pydantic import Field, SecretStr
1010
from pydantic_settings import BaseSettings, SettingsConfigDict
1111

@@ -24,10 +24,25 @@ def default_audit_log_path() -> str:
2424
return str(Path(user_state_dir(APP_NAME)) / "audit.jsonl")
2525

2626

27+
def global_config_path() -> Path:
28+
return Path(user_config_dir(APP_NAME)) / ".env"
29+
30+
31+
def find_env_file() -> str | None:
32+
"""Find .env file: local first, then global."""
33+
local = Path(".env")
34+
if local.exists():
35+
return str(local)
36+
global_path = global_config_path()
37+
if global_path.exists():
38+
return str(global_path)
39+
return None
40+
41+
2742
class AppSettings(BaseSettings):
2843
model_config = SettingsConfigDict(
2944
env_prefix="O2SWITCH_CLI_",
30-
env_file=".env",
45+
env_file=find_env_file(),
3146
env_file_encoding="utf-8",
3247
env_ignore_empty=True,
3348
extra="ignore",

0 commit comments

Comments
 (0)