mona-cli 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
mona/__init__.py ADDED
File without changes
mona/cli.py ADDED
@@ -0,0 +1,32 @@
1
+ # mona/cli.py
2
+ import click
3
+ from mona.sync import run_sync
4
+ from pathlib import Path
5
+ import shutil
6
+
7
+ TEMPLATE_PATH = Path(__file__).parent / "templates" / "example.toml"
8
+
9
+
10
+ @click.group()
11
+ def cli():
12
+ """Mona – sync your local config to Lisa"""
13
+ pass
14
+
15
+
16
+ @cli.command()
17
+ def sync():
18
+ """Sync config variables across project"""
19
+ click.echo("...")
20
+ run_sync()
21
+
22
+
23
+ @cli.command()
24
+ def init():
25
+ """Initialize a template"""
26
+ try:
27
+ open("lisa.toml", "x").close()
28
+ except FileExistsError:
29
+ raise SystemExit("lisa.toml already exists")
30
+ shutil.copy(TEMPLATE_PATH, "lisa.toml")
31
+
32
+ click.echo("created lisa.toml")
mona/config.py ADDED
@@ -0,0 +1,14 @@
1
+ # mona/config.py
2
+ import os
3
+ from dotenv import load_dotenv
4
+
5
+ load_dotenv()
6
+
7
+
8
+ CONFIG_API = os.environ.get("LISA_CONFIG_API")
9
+ SERVER_URL = os.environ.get("LISA_SERVER_URL", "https://lisa-aopa.onrender.com")
10
+
11
+
12
+ def validate():
13
+ if not CONFIG_API:
14
+ raise EnvironmentError("LISA_CONFIG_API is not set in your .env file")
mona/sync.py ADDED
@@ -0,0 +1,78 @@
1
+ # mona/sync.py
2
+ import tomllib
3
+ import json
4
+ import requests
5
+ from mona.config import CONFIG_API, SERVER_URL, validate
6
+
7
+
8
+ def _infer_type(value) -> str:
9
+ if isinstance(value, bool):
10
+ return "boolean"
11
+ if isinstance(value, int) or isinstance(value, float):
12
+ return "number"
13
+ if isinstance(value, dict):
14
+ return "json"
15
+ return "string"
16
+
17
+
18
+ def _serialize_value(value) -> str:
19
+ if isinstance(value, bool):
20
+ return "true" if value else "false"
21
+ if isinstance(value, dict):
22
+ return json.dumps(value)
23
+ return str(value)
24
+
25
+
26
+ def _prepare_payload(data: dict) -> dict:
27
+ return {
28
+ key: {
29
+ "value": _serialize_value(val),
30
+ "value_type": _infer_type(val),
31
+ }
32
+ for key, val in data.items()
33
+ }
34
+
35
+
36
+ def run_sync():
37
+ validate()
38
+
39
+ try:
40
+ with open("lisa.toml", "rb") as f:
41
+ data = tomllib.load(f)
42
+ except FileNotFoundError:
43
+ raise SystemExit("lisa.toml not found — run `mona init` first")
44
+
45
+ url = f"{SERVER_URL}/sync/{CONFIG_API}"
46
+ response = requests.post(url, json=_prepare_payload(data))
47
+
48
+ if response.status_code != 200:
49
+ raise SystemExit(f"Server error {response.status_code}: {response.text}")
50
+
51
+ _print_diff(response.json())
52
+
53
+
54
+ def _print_diff(result: dict):
55
+ added = result.get("added", [])
56
+ updated = result.get("updated", [])
57
+ removed = result.get("deleted", [])
58
+
59
+ if not any([added, updated, removed]):
60
+ print("already in sync, no changes made")
61
+ return
62
+
63
+ if added:
64
+ print(f"\n added ({len(added)})")
65
+ for key in added:
66
+ print(f" + {key}")
67
+
68
+ if updated:
69
+ print(f"\n updated ({len(updated)})")
70
+ for key in updated:
71
+ print(f" ~ {key}")
72
+
73
+ if removed:
74
+ print(f"\n removed ({len(removed)})")
75
+ for key in removed:
76
+ print(f" - {key}")
77
+
78
+ print()
@@ -0,0 +1,25 @@
1
+ # lisa.toml
2
+ # to sync with lisa run 'mona sync'
3
+ # supported types: string, int, float, bool, inline table (json)
4
+
5
+ string_param = "hi"
6
+ float_param = 0.0
7
+ bool_param = true
8
+
9
+ json_param = {
10
+ "key": "value"
11
+ }
12
+
13
+ # nested tables resolve to nested json
14
+ # the code below is the same as
15
+ # nested_table = {
16
+ # shallow_level = 1,
17
+ # deeper_nest = {
18
+ # deep_level = 2
19
+ # }
20
+ # }
21
+ # are the same things
22
+ [nested_table]
23
+ shallow_level = "top"
24
+ [deeper_nest]
25
+ deep_level = "deep"
@@ -0,0 +1,98 @@
1
+ Metadata-Version: 2.4
2
+ Name: mona-cli
3
+ Version: 0.1.0
4
+ Summary: CLI tool for syncing local config files to a Lisa remote config server
5
+ Requires-Python: >=3.13
6
+ Requires-Dist: click>=8.3.1
7
+ Requires-Dist: python-dotenv>=1.2.2
8
+ Requires-Dist: requests>=2.32.5
9
+ Description-Content-Type: text/markdown
10
+
11
+ # Mona cli
12
+ Mona is the cli-interface for configuring your lisa projects
13
+
14
+ ---
15
+
16
+ ## Features
17
+
18
+ - Initialize configuration templates for new projects
19
+ - Sync remote config variables with lisa
20
+ - Works with `.env` files via python-dotenv
21
+ - Simple CLI interface built with Click
22
+
23
+ ---
24
+
25
+ ## Installation
26
+
27
+ Once published to PyPI:
28
+
29
+ ```bash
30
+ pip install mona-cli
31
+ ````
32
+
33
+ Using uv:
34
+
35
+ ```bash
36
+ uv pip install mona-cli
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Usage
42
+
43
+ After installation, the `mona` command is available on the system PATH.
44
+
45
+ ```bash
46
+ mona --help
47
+ ```
48
+
49
+ Expected output:
50
+
51
+ ```bash
52
+ Usage: mona [OPTIONS] COMMAND [ARGS]...
53
+
54
+ Mona – sync your local config to Lisa
55
+
56
+ Options:
57
+ --help Show this message and exit.
58
+
59
+ Commands:
60
+ init Initialize a template
61
+ sync Sync config variables across project
62
+ ```
63
+
64
+ ---
65
+
66
+ ## Usage
67
+ ### mona init
68
+
69
+ Initializes a configuration template in the current project.
70
+
71
+ ```bash
72
+ mona init
73
+ ```
74
+
75
+ ### mona sync
76
+
77
+ Synchronizes local configuration values with the Lisa remote configuration server.
78
+
79
+ ```bash
80
+ mona sync
81
+ ```
82
+ ---
83
+
84
+ ## Configuration
85
+
86
+ Mona requires your project config_api\
87
+ To generate a project run
88
+ ```bash
89
+ curl -X POST https://lisa-aopa.onrender.com/create/<project_name>
90
+ ```
91
+ and copy the returned client and config apis to a safe place as they\
92
+ will not be displayed again
93
+
94
+ ```env
95
+ LISA_CONFIG_URL=https://config.example.com
96
+ ```
97
+ Environment variables are loaded automatically using python-dotenv.
98
+
@@ -0,0 +1,9 @@
1
+ mona/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ mona/cli.py,sha256=GNTNvQN-Wj18YCHoIkDQ_6qYwnwyA2NVo6kV0UQurvg,638
3
+ mona/config.py,sha256=6BpBfAmZC8THlHhjkeKwhWmZOYUGrvJtr7K2aHL9qOA,323
4
+ mona/sync.py,sha256=v5YkQx-Xkvwwt795tKNaO3mKBppbGpZoaNjsZcj0Sv0,1903
5
+ mona/templates/example.toml,sha256=4ROx4t0eDwPg_jvGABwN_uFWAPayjMa0FMgY1HsUwwE,465
6
+ mona_cli-0.1.0.dist-info/METADATA,sha256=y1WAErxoEgr6ZYgchPXOJyGYVXjhuGxZkFpigraD3M0,1679
7
+ mona_cli-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
8
+ mona_cli-0.1.0.dist-info/entry_points.txt,sha256=at1VJVOQf9WVzx71NHkPTF5_zkXDJhHrTCaTrMDkAF4,38
9
+ mona_cli-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ mona = mona.cli:cli