sing-box-cli 0.0.27__tar.gz → 0.0.29__tar.gz

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.
Files changed (32) hide show
  1. {sing_box_cli-0.0.27 → sing_box_cli-0.0.29}/CHANGELOG.md +22 -0
  2. {sing_box_cli-0.0.27 → sing_box_cli-0.0.29}/PKG-INFO +4 -4
  3. {sing_box_cli-0.0.27 → sing_box_cli-0.0.29}/pyproject.toml +8 -8
  4. {sing_box_cli-0.0.27/src/sing_box_service → sing_box_cli-0.0.29/src/sing_box_cli}/__init__.py +1 -1
  5. {sing_box_cli-0.0.27/src/sing_box_service → sing_box_cli-0.0.29/src/sing_box_cli}/common.py +6 -0
  6. {sing_box_cli-0.0.27/src/sing_box_service → sing_box_cli-0.0.29/src/sing_box_cli}/config/__init__.py +19 -8
  7. {sing_box_cli-0.0.27/src/sing_box_service → sing_box_cli-0.0.29/src/sing_box_cli}/main.py +12 -16
  8. {sing_box_cli-0.0.27/src/sing_box_service → sing_box_cli-0.0.29/src/sing_box_cli}/service/__init__.py +15 -15
  9. {sing_box_cli-0.0.27/src/sing_box_service → sing_box_cli-0.0.29/src/sing_box_cli}/service/manager.py +1 -14
  10. {sing_box_cli-0.0.27 → sing_box_cli-0.0.29}/tests/test_config.py +1 -1
  11. {sing_box_cli-0.0.27 → sing_box_cli-0.0.29}/.github/dependabot.yml +0 -0
  12. {sing_box_cli-0.0.27 → sing_box_cli-0.0.29}/.github/workflows/main.yml +0 -0
  13. {sing_box_cli-0.0.27 → sing_box_cli-0.0.29}/.gitignore +0 -0
  14. {sing_box_cli-0.0.27 → sing_box_cli-0.0.29}/.pre-commit-config.yaml +0 -0
  15. {sing_box_cli-0.0.27 → sing_box_cli-0.0.29}/LICENSE +0 -0
  16. {sing_box_cli-0.0.27 → sing_box_cli-0.0.29}/README.md +0 -0
  17. {sing_box_cli-0.0.27 → sing_box_cli-0.0.29}/assets/image.png +0 -0
  18. {sing_box_cli-0.0.27 → sing_box_cli-0.0.29}/scripts/bump.sh +0 -0
  19. {sing_box_cli-0.0.27 → sing_box_cli-0.0.29}/scripts/format.sh +0 -0
  20. {sing_box_cli-0.0.27 → sing_box_cli-0.0.29}/scripts/lint.sh +0 -0
  21. {sing_box_cli-0.0.27 → sing_box_cli-0.0.29}/scripts/pre-commit.sh +0 -0
  22. {sing_box_cli-0.0.27/src/sing_box_service → sing_box_cli-0.0.29/src/sing_box_cli}/api/__init__.py +0 -0
  23. {sing_box_cli-0.0.27/src/sing_box_service → sing_box_cli-0.0.29/src/sing_box_cli}/api/client.py +0 -0
  24. {sing_box_cli-0.0.27/src/sing_box_service → sing_box_cli-0.0.29/src/sing_box_cli}/api/connections.py +0 -0
  25. {sing_box_cli-0.0.27/src/sing_box_service → sing_box_cli-0.0.29/src/sing_box_cli}/api/logs.py +0 -0
  26. {sing_box_cli-0.0.27/src/sing_box_service → sing_box_cli-0.0.29/src/sing_box_cli}/api/monitor.py +0 -0
  27. {sing_box_cli-0.0.27/src/sing_box_service → sing_box_cli-0.0.29/src/sing_box_cli}/api/policy.py +0 -0
  28. {sing_box_cli-0.0.27/src/sing_box_service → sing_box_cli-0.0.29/src/sing_box_cli}/api/widget.py +0 -0
  29. {sing_box_cli-0.0.27/src/sing_box_service → sing_box_cli-0.0.29/src/sing_box_cli}/config/config.py +0 -0
  30. {sing_box_cli-0.0.27/src/sing_box_service → sing_box_cli-0.0.29/src/sing_box_cli}/config/utils.py +0 -0
  31. {sing_box_cli-0.0.27/src/sing_box_service → sing_box_cli-0.0.29/src/sing_box_cli}/py.typed +0 -0
  32. {sing_box_cli-0.0.27 → sing_box_cli-0.0.29}/uv.lock +0 -0
@@ -2,6 +2,28 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## 0.0.29 - 2025-03-22
6
+
7
+ ### 🚀 Features
8
+
9
+ - Add update option for `run` and `service restart` to update config automatically
10
+ - Add `--restart` option for `config add-sub`
11
+
12
+ ### 📚 Documentation
13
+
14
+ - Fix email
15
+
16
+ ### ⚙️ Miscellaneous Tasks
17
+
18
+ - Rename dir sing_box_service as sing_box_cli
19
+ - Replace creating service instance manually with context object
20
+
21
+ ## 0.0.28 - 2025-03-21
22
+
23
+ ### ⚙️ Miscellaneous Tasks
24
+
25
+ - Remove commands about capture logs in windows
26
+
5
27
  ## 0.0.27 - 2025-03-21
6
28
 
7
29
  ### 🐛 Bug Fixes
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sing-box-cli
3
- Version: 0.0.27
4
- Summary: cross-platform sing-box-service manager.
3
+ Version: 0.0.29
4
+ Summary: cross-platform sing-box manager.
5
5
  Project-URL: Homepage, https://github.com/aittcuszz/sing-box-service
6
6
  Project-URL: Issues, https://github.com/atticuszz/sing-box-service/issues
7
7
  Project-URL: documentation, https://atticuszz.github.io/sing-box-service/
8
8
  Project-URL: Changelog, https://github.com/atticuszz/sing-box-service/blob/main/CHANGELOG.md
9
- Author-email: "A.J.Zeller" <zhouge1831@gmail.com>
10
- Maintainer-email: "A.J.Zeller" <zhouge1831@gmail.com>
9
+ Author-email: "A.J.Zeller" <hello@atticux.me>
10
+ Maintainer-email: "A.J.Zeller" <hello@atticux.me>
11
11
  License: MIT License
12
12
 
13
13
  Copyright (c) 2024 A.J.Zeller
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
5
5
 
6
6
  [project]
7
7
  name = "sing-box-cli"
8
- description = "cross-platform sing-box-service manager."
8
+ description = "cross-platform sing-box manager."
9
9
  classifiers = [
10
10
  "License :: OSI Approved :: MIT License",
11
11
  "Programming Language :: Python",
@@ -19,8 +19,8 @@ classifiers = [
19
19
  readme = "README.md"
20
20
  requires-python = ">=3.10"
21
21
  license = { file = "LICENSE" }
22
- authors = [{ name = "A.J.Zeller", email = "zhouge1831@gmail.com" }]
23
- maintainers = [{ name = "A.J.Zeller", email = "zhouge1831@gmail.com" }]
22
+ authors = [{ name = "A.J.Zeller", email = "hello@atticux.me" }]
23
+ maintainers = [{ name = "A.J.Zeller", email = "hello@atticux.me" }]
24
24
 
25
25
  dynamic = ["version"] # https://hatch.pypa.io/latest/config/metadata/#version
26
26
  dependencies = [
@@ -39,7 +39,7 @@ documentation = "https://atticuszz.github.io/sing-box-service/"
39
39
  Changelog = "https://github.com/atticuszz/sing-box-service/blob/main/CHANGELOG.md"
40
40
 
41
41
  [project.scripts] # build-backend config needed
42
- sing-box-cli = "sing_box_service:main" # equal to from python import main; then run main()
42
+ sing-box-cli = "sing_box_cli:main" # equal to from python import main; then run main()
43
43
  # FROM: https://packaging.python.org/en/latest/guides/writing-pyproject-toml/
44
44
 
45
45
  [tool.uv]
@@ -65,11 +65,11 @@ dev = [
65
65
  ]
66
66
 
67
67
  [tool.hatch.version]
68
- path = "src/sing_box_service/__init__.py"
68
+ path = "src/sing_box_cli/__init__.py"
69
69
  # FROM: https://hatch.pypa.io/latest/version/
70
70
 
71
71
  [tool.hatch.build.targets.wheel]
72
- packages = ["src/sing_box_service"]
72
+ packages = ["src/sing_box_cli"]
73
73
  # FROM: https://hatch.pypa.io/latest/build/
74
74
 
75
75
 
@@ -213,7 +213,7 @@ sort_commits = "oldest"
213
213
 
214
214
 
215
215
  [tool.bumpversion]
216
- current_version = "0.0.27"
216
+ current_version = "0.0.29"
217
217
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
218
218
  serialize = ["{major}.{minor}.{patch}"]
219
219
  search = "{current_version}"
@@ -234,7 +234,7 @@ pre_commit_hooks = []
234
234
  post_commit_hooks = []
235
235
 
236
236
  [[tool.bumpversion.files]]
237
- filename = "src/sing_box_service/__init__.py"
237
+ filename = "src/sing_box_cli/__init__.py"
238
238
 
239
239
  [[tool.bumpversion.files]]
240
240
  filename = "CHANGELOG.md"
@@ -2,4 +2,4 @@ from .main import main
2
2
 
3
3
  __all__ = ["main"]
4
4
 
5
- __version__ = "0.0.27"
5
+ __version__ = "0.0.29"
@@ -1,7 +1,13 @@
1
1
  import os
2
2
  from enum import Enum
3
+ from typing import Annotated
4
+
5
+ import typer
3
6
 
4
7
  StrOrNone = str | None
8
+ UpdateConfigOption = Annotated[
9
+ bool, typer.Option("--update", "-u", help="Update configuration before running.")
10
+ ]
5
11
 
6
12
 
7
13
  class LogLevel(str, Enum):
@@ -7,22 +7,33 @@ from .config import SingBoxConfig, get_config
7
7
 
8
8
  __all__ = ["config", "SingBoxConfig", "get_config"]
9
9
 
10
+ SubUrlArg = Annotated[str, typer.Argument(help="Subscription URL")]
11
+ RestartServiceOption = Annotated[
12
+ bool, typer.Option("--restart", "-r", help="Restart service after update.")
13
+ ]
14
+
10
15
  config = typer.Typer(help="Configuration management commands")
11
16
 
12
17
 
13
18
  @config.command("add-sub")
14
- def config_add_sub(ctx: typer.Context, url: Annotated[str, typer.Argument()]) -> None:
15
- """Add subscription URL"""
16
- ensure_root()
19
+ def config_add_sub(
20
+ ctx: typer.Context, url: SubUrlArg, restart: RestartServiceOption = False
21
+ ) -> None:
22
+ """Add subscription URL, download configuration and restart service if needed"""
17
23
  if ctx.obj.config.add_subscription(url):
18
- # restart service if subscription is updated
19
- if not ctx.obj.service.check_service():
20
- ctx.obj.service.create_service()
21
- print("⌛ Service created successfully.")
24
+ # download config
22
25
  if ctx.obj.config.update_config():
23
- ctx.obj.service.restart()
26
+ print("✅ Configuration updated.")
24
27
  else:
28
+ print("❌ Failed to update configuration.")
25
29
  raise typer.Exit(1)
30
+ if restart:
31
+ ensure_root()
32
+ # init service
33
+ if not ctx.obj.service.check_service():
34
+ ctx.obj.service.create_service()
35
+ print("⌛ Service created successfully.")
36
+ ctx.obj.service.restart()
26
37
  else:
27
38
  print("❌ Failed to add subscription.")
28
39
  raise typer.Exit(1)
@@ -5,7 +5,7 @@ import typer
5
5
  from rich import print
6
6
 
7
7
  from .api import api as api_app
8
- from .common import ensure_root
8
+ from .common import UpdateConfigOption, ensure_root
9
9
  from .config import SingBoxConfig, config as config_app, get_config
10
10
  from .service import (
11
11
  LinuxServiceManager,
@@ -35,26 +35,22 @@ def callback(ctx: typer.Context) -> None:
35
35
 
36
36
 
37
37
  @app.command()
38
- def run(ctx: typer.Context) -> None:
38
+ def run(ctx: typer.Context, update: UpdateConfigOption = False) -> None:
39
39
  """Run sing-box if host's service unavailable"""
40
40
  ensure_root()
41
41
  cfg = ctx.obj.config
42
- if cfg.update_config():
43
- cmd = [
44
- cfg.bin_path,
45
- "run",
46
- "-C",
47
- str(cfg.install_dir),
48
- "-D",
49
- str(cfg.install_dir),
50
- ]
51
- if cfg.is_windows:
52
- subprocess.run(["pwsh"] + cmd)
42
+ if update:
43
+ if cfg.update_config():
44
+ print("✅ Configuration updated.")
53
45
  else:
54
- subprocess.run(cmd)
46
+ print("❌ Failed to update configuration.")
47
+ raise typer.Exit(1)
48
+
49
+ cmd = [cfg.bin_path, "run", "-C", str(cfg.config_dir), "-D", str(cfg.config_dir)]
50
+ if cfg.is_windows:
51
+ subprocess.run(["pwsh"] + cmd)
55
52
  else:
56
- print("❌ Failed to update configuration.")
57
- raise typer.Exit(1)
53
+ subprocess.run(cmd)
58
54
 
59
55
 
60
56
  @app.command()
@@ -1,6 +1,6 @@
1
1
  import typer
2
2
 
3
- from ..common import ensure_root
3
+ from ..common import UpdateConfigOption, ensure_root
4
4
  from .manager import LinuxServiceManager, WindowsServiceManager, create_service
5
5
 
6
6
  __all__ = ["service", "WindowsServiceManager", "LinuxServiceManager", "create_service"]
@@ -14,7 +14,7 @@ def service_enable(ctx: typer.Context) -> None:
14
14
  """Create sing-box service, enable autostart and start service"""
15
15
  ensure_root()
16
16
  config = ctx.obj.config
17
- service = create_service(config)
17
+ service = ctx.obj.service
18
18
  service.create_service()
19
19
  service.start()
20
20
  print("🔥 Service started.")
@@ -26,26 +26,28 @@ def service_enable(ctx: typer.Context) -> None:
26
26
  def service_disable(ctx: typer.Context) -> None:
27
27
  """Stop service, disable sing-box service autostart and remove service"""
28
28
  ensure_root()
29
- config = ctx.obj.config
30
- service = create_service(config)
29
+ service = ctx.obj.service
31
30
  service.stop()
32
31
  service.disable()
33
32
  print("✋ Autostart disabled.")
34
33
 
35
34
 
36
35
  @service.command("restart")
37
- def service_restart(ctx: typer.Context) -> None:
36
+ def service_restart(ctx: typer.Context, update: UpdateConfigOption = False) -> None:
38
37
  """Restart sing-box service, update configuration if needed, create service if not exists"""
39
38
  ensure_root()
40
39
  config = ctx.obj.config
41
- service = create_service(config)
40
+ service = ctx.obj.service
42
41
  if not service.check_service():
43
42
  service.create_service()
44
- if config.update_config():
45
- service.restart()
46
- else:
47
- print("❌ Failed to update configuration.")
48
- raise typer.Exit(1)
43
+ if update:
44
+ if config.update_config():
45
+ print("✅ Configuration updated.")
46
+ else:
47
+ print("❌ Failed to update configuration.")
48
+ raise typer.Exit(1)
49
+
50
+ service.restart()
49
51
  print("🔥 Service restarted.")
50
52
  if config.api_base_url:
51
53
  print(f"🔌 Default API: {config.api_base_url}")
@@ -55,8 +57,7 @@ def service_restart(ctx: typer.Context) -> None:
55
57
  def service_stop(ctx: typer.Context) -> None:
56
58
  """Stop sing-box service"""
57
59
  ensure_root()
58
- config = ctx.obj.config
59
- service = create_service(config)
60
+ service = ctx.obj.service
60
61
  service.stop()
61
62
  print("✋ Service stopped.")
62
63
 
@@ -65,7 +66,6 @@ def service_stop(ctx: typer.Context) -> None:
65
66
  def service_status(ctx: typer.Context) -> None:
66
67
  """Check service status"""
67
68
  ensure_root()
68
- config = ctx.obj.config
69
- service = create_service(config)
69
+ service = ctx.obj.service
70
70
  status = service.status()
71
71
  print(f"🏃 Service status: {status}")
@@ -38,7 +38,6 @@ class WindowsServiceManager(ServiceManager):
38
38
  def __init__(self, config: SingBoxConfig) -> None:
39
39
  super().__init__(config)
40
40
  self.task_name = "sing-box-service"
41
- self.log_file = self.config.config_dir / "sing-box.log"
42
41
 
43
42
  def create_service(self) -> None:
44
43
  start_script = self.config.config_dir / "start-singbox.ps1"
@@ -52,21 +51,9 @@ public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
52
51
  $console = [Console.Window]::GetConsoleWindow()
53
52
  [Console.Window]::ShowWindow($console, 0)
54
53
 
55
- [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
56
- $OutputEncoding = [System.Text.Encoding]::UTF8
57
- chcp 65001 | Out-Null
58
-
59
54
  Set-Location "{self.config.config_dir}"
60
55
 
61
- if (Test-Path "{self.log_file}") {{
62
- Clear-Content "{self.log_file}"
63
- }}
64
-
65
- try {{
66
- & "{self.config.bin_path}" run -C "{self.config.config_dir}" *>&1 | Tee-Object -FilePath "{self.log_file}" -Append
67
- }} catch {{
68
- $_ | Out-File -FilePath "{self.log_file}" -Append
69
- }}
56
+ & "{self.config.bin_path}" run -C "{self.config.config_dir}"
70
57
  """
71
58
  start_script.write_text(script_content, encoding="utf-8")
72
59
 
@@ -1,6 +1,6 @@
1
1
  import pytest
2
2
 
3
- from sing_box_service.config.utils import show_diff_config
3
+ from sing_box_cli.config.utils import show_diff_config
4
4
 
5
5
 
6
6
  def test_show_diff_config(capsys: pytest.CaptureFixture[str]) -> None:
File without changes
File without changes
File without changes
File without changes