Skip to content

Commit 8935a44

Browse files
committed
Add Config CLI parser
and store config file.
1 parent 3603067 commit 8935a44

File tree

2 files changed

+92
-4
lines changed

2 files changed

+92
-4
lines changed

client/src/cli/commands/config.py

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import argparse
2+
from typing import Any
3+
4+
import yaml
5+
6+
from .util import Config
7+
8+
9+
def handle_config(args: argparse.Namespace) -> None:
10+
config = Config()
11+
if args.config_action == "view":
12+
if args.key:
13+
value = config.get(args.key)
14+
print(f"{args.key}: {value}")
15+
else:
16+
print(yaml.dump(config.data))
17+
elif args.config_action == "set":
18+
config.set(args.key, args.value)
19+
20+
21+
def add_parser(subparsers: Any, parent: argparse.ArgumentParser) -> None:
22+
parser: argparse.ArgumentParser = subparsers.add_parser(
23+
"config", parents=[parent], description="Configure Jobq"
24+
)
25+
26+
config_subparsers = parser.add_subparsers(
27+
dest="config_action", help="Config actions"
28+
)
29+
30+
view_parser = config_subparsers.add_parser(
31+
"view", help="View current configuration"
32+
)
33+
view_parser.add_argument("--key", help="Specific config key to view")
34+
35+
set_parser = config_subparsers.add_parser("set", help="Set a configuration value")
36+
set_parser.add_argument("key", help="Configuration key to set")
37+
set_parser.add_argument("value", help="Value to set for the key")
38+
39+
parser.set_defaults(func=handle_config, config_action="view")

client/src/cli/commands/util.py

+53-4
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,68 @@
1+
from __future__ import annotations
2+
13
from collections.abc import Callable
24
from functools import wraps
3-
from typing import Concatenate, ParamSpec, TypeVar
5+
from pathlib import Path
6+
from typing import Any, Concatenate, ParamSpec, TypeVar, cast
7+
8+
import yaml
49

510
import openapi_client
611
from openapi_client.exceptions import ApiException
712

8-
# TODO: Factor backend host url into some kind of config file
9-
BACKEND_HOST = "http://localhost:8000"
13+
DEFAULT_CONFIG = {"backend": {"host": "http://localhost:8000"}}
14+
CONFIG_PATH = Path.home() / ".config" / "jobq" / "config.yaml"
15+
16+
17+
C = TypeVar("C", bound="Config")
18+
19+
20+
class Config:
21+
_instance: Config | None = None
22+
data: dict[str, Any]
23+
24+
def __new__(cls: type[C]) -> C:
25+
if cls._instance is None:
26+
cls._instance = super().__new__(cls)
27+
cls._instance.data = cls._instance.load()
28+
return cast(C, cls._instance)
29+
30+
def load(self) -> dict[str, Any]:
31+
if CONFIG_PATH.exists():
32+
return yaml.safe_load(CONFIG_PATH.read_text())
33+
return DEFAULT_CONFIG.copy()
34+
35+
def save(self) -> None:
36+
CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True)
37+
CONFIG_PATH.write_text(yaml.dump(self.data))
38+
39+
def get(self, key: str) -> Any:
40+
keys = key.split(".")
41+
value = self.data
42+
for k in keys:
43+
if isinstance(value, dict) and k in value:
44+
value = value[k]
45+
else:
46+
raise ValueError(f"Didnot find {key} in config")
47+
return value
48+
49+
def set(self, key: str, value: str) -> None:
50+
keys = key.split(".")
51+
data = self.data
52+
for k in keys[:-1]:
53+
if k not in data:
54+
data[k] = {}
55+
data = data[k]
56+
data[keys[-1]] = value
57+
self.save()
58+
1059

1160
T = TypeVar("T")
1261
P = ParamSpec("P")
1362

1463

1564
def _make_api_client() -> openapi_client.ApiClient:
16-
api_config = openapi_client.Configuration(host=BACKEND_HOST)
65+
api_config = openapi_client.Configuration(host=Config().get("backend.host"))
1766
return openapi_client.ApiClient(api_config)
1867

1968

0 commit comments

Comments
 (0)